diff --git a/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift index 0ed583ffa..0a45218a4 100644 --- a/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift @@ -47,153 +47,6 @@ extension DarwinToolchain { return try findXcodeClangLibPath("arc") } - internal func addLTOLibArgs(to commandLine: inout [Job.ArgTemplate]) throws { - if let path = try findXcodeClangLibPath("libLTO.dylib") { - commandLine.appendFlag("-lto_library") - commandLine.appendPath(path) - } - } - - func addLinkRuntimeLibraryRPath( - to commandLine: inout [Job.ArgTemplate], - parsedOptions: inout ParsedOptions, - targetInfo: FrontendTargetInfo, - darwinLibName: String - ) throws { - // Adding the rpaths might negatively interact when other rpaths are involved, - // so we should make sure we add the rpaths last, after all user-specified - // rpaths. This is currently true from this place, but we need to be - // careful if this function is ever called before user's rpaths are emitted. - assert(darwinLibName.hasSuffix(".dylib"), "must be a dynamic library") - - // Add @executable_path to rpath to support having the dylib copied with - // the executable. - commandLine.appendFlag("-rpath") - commandLine.appendFlag("@executable_path") - - // Add the path to the resource dir to rpath to support using the dylib - // from the default location without copying. - - - let clangPath = try clangLibraryPath( - for: targetInfo, - parsedOptions: &parsedOptions) - commandLine.appendFlag("-rpath") - commandLine.appendPath(clangPath) - } - - func addLinkSanitizerLibArgsForDarwin( - to commandLine: inout [Job.ArgTemplate], - parsedOptions: inout ParsedOptions, - targetInfo: FrontendTargetInfo, - sanitizer: Sanitizer, - isShared: Bool - ) throws { - // Sanitizer runtime libraries requires C++. - commandLine.appendFlag("-lc++") - // Add explicit dependency on -lc++abi, as -lc++ doesn't re-export - // all RTTI-related symbols that are used. - commandLine.appendFlag("-lc++abi") - - let sanitizerName = try runtimeLibraryName( - for: sanitizer, - targetTriple: targetInfo.target.triple, - isShared: isShared - ) - try addLinkRuntimeLibrary( - named: sanitizerName, - to: &commandLine, - for: targetInfo, - parsedOptions: &parsedOptions - ) - - if isShared { - try addLinkRuntimeLibraryRPath( - to: &commandLine, - parsedOptions: &parsedOptions, - targetInfo: targetInfo, - darwinLibName: sanitizerName - ) - } - } - - private func addProfileGenerationArgs( - to commandLine: inout [Job.ArgTemplate], - parsedOptions: inout ParsedOptions, - targetInfo: FrontendTargetInfo - ) throws { - guard parsedOptions.hasArgument(.profileGenerate) else { return } - let clangPath = try clangLibraryPath(for: targetInfo, - parsedOptions: &parsedOptions) - - for runtime in targetInfo.target.triple.darwinPlatform!.profileLibraryNameSuffixes { - let clangRTPath = clangPath - .appending(component: "libclang_rt.profile_\(runtime).a") - commandLine.appendPath(clangRTPath) - } - } - - private func addPlatformVersionArg(to commandLine: inout [Job.ArgTemplate], - for triple: Triple, sdkPath: VirtualPath.Handle?) { - assert(triple.isDarwin) - let platformName = triple.darwinPlatform!.linkerPlatformName - let platformVersion = triple.darwinLinkerPlatformVersion - let sdkVersion: Version - if let sdkPath = sdkPath, - let sdkInfo = getTargetSDKInfo(sdkPath: sdkPath) { - sdkVersion = sdkInfo.sdkVersion(for: triple) - } else { - sdkVersion = Version(0, 0, 0) - } - - commandLine.append(.flag("-platform_version")) - commandLine.append(.flag(platformName)) - commandLine.append(.flag(platformVersion.description)) - commandLine.append(.flag(sdkVersion.description)) - } - - private func addDeploymentTargetArgs( - to commandLine: inout [Job.ArgTemplate], - targetTriple: Triple, - targetVariantTriple: Triple?, - sdkPath: VirtualPath.Handle? - ) { - addPlatformVersionArg(to: &commandLine, for: targetTriple, sdkPath: sdkPath) - if let variantTriple = targetVariantTriple { - assert(targetTriple.isValidForZipperingWithTriple(variantTriple)) - addPlatformVersionArg(to: &commandLine, for: variantTriple, - sdkPath: sdkPath) - } - } - - private func addArgsToLinkARCLite( - to commandLine: inout [Job.ArgTemplate], - parsedOptions: inout ParsedOptions, - targetTriple: Triple - ) throws { - guard parsedOptions.hasFlag( - positive: .linkObjcRuntime, - negative: .noLinkObjcRuntime, - default: !targetTriple.supports(.nativeARC) - ) else { - return - } - - guard let arcLiteLibPath = try findARCLiteLibPath(), - let platformName = targetTriple.platformName() else { - return - } - let fullLibPath = arcLiteLibPath - .appending(components: "libarclite_\(platformName).a") - - commandLine.appendFlag("-force_load") - commandLine.appendPath(fullLibPath) - - // Arclite depends on CoreFoundation. - commandLine.appendFlag(.framework) - commandLine.appendFlag("CoreFoundation") - } - /// Adds the arguments necessary to link the files from the given set of /// options for a Darwin platform. public func addPlatformSpecificLinkerArgs( @@ -213,7 +66,7 @@ extension DarwinToolchain { case .dynamicLibrary: // Same as an executable, but with the -dylib flag linkerTool = .dynamicLinker - commandLine.appendFlag("-dylib") + commandLine.appendFlag("-dynamiclib") addLinkInputs(shouldUseInputFileList: shouldUseInputFileList, commandLine: &commandLine, inputs: inputs, @@ -280,8 +133,7 @@ extension DarwinToolchain { commandLine.appendPath(fileList) if linkerOutputType != .staticLibrary { for module in inputModules { - commandLine.append(.flag("-add_ast_path")) - commandLine.append(.path(module)) + commandLine.append(.joinedOptionAndPath("-Wl,-add_ast_path,", module)) } } @@ -291,7 +143,7 @@ extension DarwinToolchain { commandLine.append(contentsOf: inputs.flatMap { (path: TypedVirtualPath) -> [Job.ArgTemplate] in if path.type == .swiftModule && linkerOutputType != .staticLibrary { - return [.flag("-add_ast_path"), .path(path.file)] + return [.joinedOptionAndPath("-Wl,-add_ast_path,", path.file)] } else if path.type == .object { return [.path(path.file)] } else if path.type == .tbd { @@ -311,39 +163,16 @@ extension DarwinToolchain { sanitizers: Set, linkerOutputType: LinkOutputType, lto: LTOKind?) throws { - // FIXME: If we used Clang as a linker instead of going straight to ld, - // we wouldn't have to replicate a bunch of Clang's logic here. - - // Always link the regular compiler_rt if it's present. Note that the - // regular libclang_rt.a uses a fat binary for device and simulator; this is - // not true for all compiler_rt build products. - // - // Note: Normally we'd just add this unconditionally, but it's valid to build - // Swift and use it as a linker without building compiler_rt. - let targetTriple = targetInfo.target.triple - let darwinPlatformSuffix = - targetTriple.darwinPlatform!.with(.device)!.libraryNameSuffix - let compilerRTPath = - try clangLibraryPath( - for: targetInfo, - parsedOptions: &parsedOptions) - .appending(component: "libclang_rt.\(darwinPlatformSuffix).a") - if try fileSystem.exists(compilerRTPath) { - commandLine.append(.path(compilerRTPath)) - } - - try addArgsToLinkARCLite( - to: &commandLine, - parsedOptions: &parsedOptions, - targetTriple: targetTriple - ) + if let lto = lto { + switch lto { + case .llvmFull: + commandLine.appendFlag("-flto=full") + case .llvmThin: + commandLine.appendFlag("-flto=thin") + } - if lto != nil { if let arg = parsedOptions.getLastArgument(.ltoLibrary)?.asSingle { - commandLine.appendFlag("-lto_library") - commandLine.appendPath(try VirtualPath(path: arg)) - } else { - try addLTOLibArgs(to: &commandLine) + commandLine.append(.joinedOptionAndPath("-Wl,-lto_library,", try VirtualPath(path: arg))) } } @@ -354,43 +183,44 @@ extension DarwinToolchain { } if parsedOptions.contains(.enableAppExtension) { - commandLine.appendFlag("-application_extension") + commandLine.appendFlag("-fapplication-extension") } // Linking sanitizers will add rpaths, which might negatively interact when // other rpaths are involved, so we should make sure we add the rpaths after // all user-specified rpaths. - for sanitizer in sanitizers { - if sanitizer == .fuzzer { - guard linkerOutputType == .executable else { continue } - } - try addLinkSanitizerLibArgsForDarwin( - to: &commandLine, - parsedOptions: &parsedOptions, - targetInfo: targetInfo, - sanitizer: sanitizer, - isShared: sanitizer != .fuzzer - ) + if linkerOutputType == .executable && !sanitizers.isEmpty { + let sanitizerNames = sanitizers + .map { $0.rawValue } + .sorted() // Sort so we get a stable, testable order + .joined(separator: ",") + commandLine.appendFlag("-fsanitize=\(sanitizerNames)") } - if parsedOptions.contains(.embedBitcode) || - parsedOptions.contains(.embedBitcodeMarker) { - commandLine.appendFlag("-bitcode_bundle") + if parsedOptions.contains(.embedBitcode) { + commandLine.appendFlag("-fembed-bitcode") + } else if parsedOptions.contains(.embedBitcodeMarker) { + commandLine.appendFlag("-fembed-bitcode=marker") } // Add the SDK path if let sdkPath = targetInfo.sdkPath?.path { - commandLine.appendFlag("-syslibroot") + commandLine.appendFlag("--sysroot") commandLine.appendPath(VirtualPath.lookup(sdkPath)) } commandLine.appendFlags( + "-fobjc-link-runtime", "-lobjc", "-lSystem" ) - commandLine.appendFlag("-arch") - commandLine.appendFlag(targetTriple.archName) + let targetTriple = targetInfo.target.triple + commandLine.appendFlag("--target=\(targetTriple.triple)") + if let variantTriple = targetInfo.targetVariant?.triple { + assert(targetTriple.isValidForZipperingWithTriple(variantTriple)) + commandLine.appendFlag("-darwin-target-variant=\(variantTriple.triple)") + } // On Darwin, we only support libc++. if parsedOptions.contains(.enableExperimentalCxxInterop) { @@ -405,19 +235,9 @@ extension DarwinToolchain { fileSystem: fileSystem ) - try addProfileGenerationArgs( - to: &commandLine, - parsedOptions: &parsedOptions, - targetInfo: targetInfo - ) - - let targetVariantTriple = targetInfo.targetVariant?.triple - addDeploymentTargetArgs( - to: &commandLine, - targetTriple: targetTriple, - targetVariantTriple: targetVariantTriple, - sdkPath: targetInfo.sdkPath?.path - ) + if parsedOptions.hasArgument(.profileGenerate) { + commandLine.appendFlag("-fprofile-generate") + } // These custom arguments should be right before the object file at the // end. @@ -427,7 +247,13 @@ extension DarwinToolchain { from: &parsedOptions ) addLinkedLibArgs(to: &commandLine, parsedOptions: &parsedOptions) - try commandLine.appendAllArguments(.Xlinker, from: &parsedOptions) + // Because we invoke `clang` as the linker executable, we must still + // use `-Xlinker` for linker-specific arguments. + for linkerOpt in parsedOptions.arguments(for: .Xlinker) { + commandLine.appendFlag(.Xlinker) + commandLine.appendFlag(linkerOpt.argument.asSingle) + } + try commandLine.appendAllArguments(.XclangLinker, from: &parsedOptions) } } diff --git a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift index 0b3a5d071..b83bcb331 100644 --- a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift @@ -56,19 +56,6 @@ extension Toolchain { return result } - func addLinkRuntimeLibrary( - named name: String, - to commandLine: inout [Job.ArgTemplate], - for targetInfo: FrontendTargetInfo, - parsedOptions: inout ParsedOptions - ) throws { - let path = try clangLibraryPath( - for: targetInfo, - parsedOptions: &parsedOptions) - .appending(component: name) - commandLine.appendPath(path) - } - func runtimeLibraryExists( for sanitizer: Sanitizer, targetInfo: FrontendTargetInfo, diff --git a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift index a3e0e64fd..eb3067480 100644 --- a/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift +++ b/Sources/SwiftDriver/Toolchains/DarwinToolchain.swift @@ -64,7 +64,7 @@ public final class DarwinToolchain: Toolchain { case .swiftCompiler: return try lookup(executable: "swift-frontend") case .dynamicLinker: - return try lookup(executable: "ld") + return try lookup(executable: "clang") case .staticLinker: return try lookup(executable: "libtool") case .dsymutil: diff --git a/Tests/SwiftDriverTests/JobExecutorTests.swift b/Tests/SwiftDriverTests/JobExecutorTests.swift index 592bf822d..73b7deb3f 100644 --- a/Tests/SwiftDriverTests/JobExecutorTests.swift +++ b/Tests/SwiftDriverTests/JobExecutorTests.swift @@ -179,11 +179,11 @@ final class JobExecutorTests: XCTestCase { .path(.temporary(RelativePath("foo.o"))), .path(.temporary(RelativePath("main.o"))), .path(.absolute(try toolchain.clangRT.get())), - "-syslibroot", .path(.absolute(try toolchain.sdk.get())), - "-lobjc", "-lSystem", "-arch", .flag(hostTriple.archName), + "--sysroot", .path(.absolute(try toolchain.sdk.get())), + "-lobjc", "-lSystem", .flag("--target=\(hostTriple.triple)"), "-L", .path(.absolute(try toolchain.resourcesDirectory.get())), "-L", .path(.absolute(try toolchain.sdkStdlib(sdk: toolchain.sdk.get()))), - "-rpath", "/usr/lib/swift", "-macosx_version_min", "10.14.0", "-o", + "-rpath", "/usr/lib/swift", "-o", .path(.relative(RelativePath("main"))), ], inputs: [ @@ -249,12 +249,10 @@ final class JobExecutorTests: XCTestCase { tool: try toolchain.resolvedTool(.dynamicLinker), commandLine: [ .path(.temporary(RelativePath("main.o"))), - .path(.absolute(try toolchain.clangRT.get())), - "-syslibroot", .path(.absolute(try toolchain.sdk.get())), - "-lobjc", "-lSystem", "-arch", .flag(hostTriple.archName), + "--sysroot", .path(.absolute(try toolchain.sdk.get())), + "-lobjc", "-lSystem", .flag("--target=\(hostTriple.triple)"), "-L", .path(.absolute(try toolchain.resourcesDirectory.get())), "-L", .path(.absolute(try toolchain.sdkStdlib(sdk: toolchain.sdk.get()))), - "-rpath", "/usr/lib/swift", "-macosx_version_min", "10.14.0", "-o", .path(.absolute(exec)), ], inputs: [ diff --git a/Tests/SwiftDriverTests/SwiftDriverTests.swift b/Tests/SwiftDriverTests/SwiftDriverTests.swift index db1abea84..c6c5f6670 100644 --- a/Tests/SwiftDriverTests/SwiftDriverTests.swift +++ b/Tests/SwiftDriverTests/SwiftDriverTests.swift @@ -674,7 +674,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(matchTemporary(plannedJobs[0].outputs.first!.file, "foo.o")) XCTAssertEqual(plannedJobs[1].outputs.count, 1) XCTAssertTrue(matchTemporary(plannedJobs[1].outputs.first!.file, "bar.o")) - XCTAssertTrue(plannedJobs[2].tool.name.contains(driver1.targetTriple.isDarwin ? executableName("ld") : executableName("clang"))) + XCTAssertTrue(plannedJobs[2].tool.name.contains(executableName("clang"))) XCTAssertEqual(plannedJobs[2].outputs.count, 1) XCTAssertEqual(plannedJobs[2].outputs.first!.file, VirtualPath.relative(RelativePath(executableName("Test")))) @@ -1480,10 +1480,8 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(linkJob.kind, .link) let cmd = linkJob.commandLine - XCTAssertTrue(cmd.contains(.flag("-dylib"))) - XCTAssertTrue(cmd.contains(.flag("-arch"))) - XCTAssertTrue(cmd.contains(.flag("x86_64"))) - XCTAssertTrue(cmd.contains(subsequence: ["-platform_version", "macos", "10.15.0"])) + XCTAssertTrue(cmd.contains(.flag("-dynamiclib"))) + XCTAssertTrue(cmd.contains(.flag("--target=x86_64-apple-macosx10.15"))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "libTest.dylib")) XCTAssertFalse(cmd.contains(.flag("-static"))) @@ -1513,10 +1511,8 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(linkJob.kind, .link) let cmd = linkJob.commandLine - XCTAssertTrue(cmd.contains(.flag("-dylib"))) - XCTAssertTrue(cmd.contains(.flag("-arch"))) - XCTAssertTrue(cmd.contains(.flag("arm64"))) - XCTAssertTrue(cmd.contains(subsequence: ["-platform_version", "ios", "10.0.0"])) + XCTAssertTrue(cmd.contains(.flag("-dynamiclib"))) + XCTAssertTrue(cmd.contains(.flag("--target=arm64-apple-ios10.0"))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "libTest.dylib")) XCTAssertFalse(cmd.contains(.flag("-static"))) @@ -1535,11 +1531,8 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(linkJob.kind, .link) let cmd = linkJob.commandLine - XCTAssertTrue(cmd.contains(.flag("-dylib"))) - XCTAssertTrue(cmd.contains(.flag("-arch"))) - XCTAssertTrue(cmd.contains(.flag("x86_64"))) - XCTAssertTrue(cmd.contains(subsequence: ["-platform_version", "mac-catalyst", "13.1.0"])) - XCTAssertTrue(cmd.contains(.flag("13.1.0"))) + XCTAssertTrue(cmd.contains(.flag("-dynamiclib"))) + XCTAssertTrue(cmd.contains(.flag("--target=x86_64-apple-ios13.1-macabi"))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "libTest.dylib")) XCTAssertFalse(cmd.contains(.flag("-static"))) @@ -1558,7 +1551,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(linkJob.kind, .link) let cmd = linkJob.commandLine - XCTAssertTrue(cmd.contains(.flag("-dylib"))) + XCTAssertTrue(cmd.contains(.flag("-dynamiclib"))) XCTAssertTrue(cmd.contains(.flag("-w"))) XCTAssertTrue(cmd.contains(.flag("-L"))) XCTAssertTrue(cmd.contains(.path(.absolute(AbsolutePath("/tmp"))))) @@ -1568,20 +1561,37 @@ final class SwiftDriverTests: XCTestCase { XCTAssertFalse(cmd.contains(.flag("-shared"))) } - #if os(Linux) + do { + // Xlinker flags + // Ensure that Xlinker flags are passed as such to the clang linker invocation. + var driver = try Driver(args: commonArgs + [ + "-emit-library", "-L", "/tmp", "-Xlinker", "-w", + "-Xlinker", "-alias", "-Xlinker", "_foo_main", "-Xlinker", "_main", + "-Xclang-linker", "foo", "-target", "x86_64-apple-macos12.0"], env: env) + let plannedJobs = try driver.planBuild() + XCTAssertEqual(plannedJobs.count, 3) + let linkJob = plannedJobs[2] + let cmd = linkJob.commandLine + XCTAssertTrue(cmd.contains(subsequence: [ + .flag("-Xlinker"), .flag("-alias"), + .flag("-Xlinker"), .flag("_foo_main"), + .flag("-Xlinker"), .flag("_main"), + .flag("foo"), + ])) + } + do { // Xlinker flags // Ensure that Xlinker flags are passed as such to the clang linker invocation. var driver = try Driver(args: commonArgs + ["-emit-library", "-L", "/tmp", "-Xlinker", "-w", - "-Xlinker", "-rpath=$ORIGIN", + "-Xlinker", "-rpath=$ORIGIN", "-Xclang-linker", "foo", "-target", "x86_64-unknown-linux"], env: env) let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.count, 4) let linkJob = plannedJobs[3] let cmd = linkJob.commandLine - XCTAssertTrue(cmd.contains(subsequence: [.flag("-Xlinker"), .flag("-rpath=$ORIGIN")])) + XCTAssertTrue(cmd.contains(subsequence: [.flag("-Xlinker"), .flag("-rpath=$ORIGIN"), .flag("foo")])) } - #endif do { var driver = try Driver(args: commonArgs + ["-emit-library", "-no-toolchain-stdlib-rpath", @@ -1706,8 +1716,8 @@ final class SwiftDriverTests: XCTestCase { let plannedJobs1 = try driver1.planBuild() XCTAssertFalse(plannedJobs1.contains(where: { $0.kind == .autolinkExtract })) let linkJob1 = plannedJobs1.first(where: { $0.kind == .link }) - XCTAssertTrue(linkJob1?.tool.name.contains("ld")) - XCTAssertTrue(linkJob1?.commandLine.contains(.flag("-lto_library"))) + XCTAssertTrue(linkJob1?.tool.name.contains("clang")) + XCTAssertTrue(linkJob1?.commandLine.contains(.flag("-flto=thin"))) #endif var driver2 = try Driver(args: commonArgs + ["-emit-executable", "-target", "x86_64-unknown-linux", "-lto=llvm-thin"], env: env) @@ -1742,7 +1752,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(cmd.contains(.flag("-o"))) XCTAssertTrue(commandContainsTemporaryPath(cmd, "foo.o")) XCTAssertTrue(commandContainsTemporaryPath(cmd, "bar.o")) - XCTAssertTrue(cmd.contains(subsequence: [.flag("-add_ast_path"), .path(.relative(.init("Test.swiftmodule")))])) + XCTAssertTrue(cmd.contains(.joinedOptionAndPath("-Wl,-add_ast_path,", .relative(.init("Test.swiftmodule"))))) XCTAssertEqual(linkJob.outputs[0].file, try VirtualPath(path: "Test")) XCTAssertFalse(cmd.contains(.flag("-static"))) @@ -2085,30 +2095,6 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(cmd.contains(subsequence: [.flag("-force_load"), .path(.absolute(path5_1iOS))])) XCTAssertTrue(cmd.contains(subsequence: [.flag("-force_load"), .path(.absolute(pathDynamicReplacementsiOS))])) } - - // libarclite is only relevant on darwin - #if os(macOS) - do { - // Override executive paths and make sure this does not affect the location of the found - // libarclite - env["SWIFT_DRIVER_SWIFTC_EXEC"] = "/some/path/swiftc" - env["SWIFT_DRIVER_CLANG_EXEC"] = "/some/path/clang" - guard let clangPathInXcode = try? clangPathInActiveXcode() else { - throw XCTSkip() - } - let clangRelativeArcLite = clangPathInXcode.parentDirectory.parentDirectory - .appending(components: "lib", "arc", "libarclite_macosx.a") - - var driver = try Driver(args: commonArgs + ["-target", "x86_64-apple-macosx10.9"], env: env) - let plannedJobs = try driver.planBuild() - - XCTAssertEqual(3, plannedJobs.count) - let linkJob = plannedJobs[2] - XCTAssertEqual(linkJob.kind, .link) - let cmd = linkJob.commandLine - XCTAssertTrue(cmd.contains(subsequence: [.flag("-force_load"), .path(.absolute(clangRelativeArcLite))])) - } - #endif } } @@ -2203,12 +2189,7 @@ final class SwiftDriverTests: XCTestCase { let linkJob = plannedJobs[2] let linkCmd = linkJob.commandLine - XCTAssertTrue(linkCmd.contains { - if case .path(let path) = $0 { - return path.name.contains("darwin/libclang_rt.asan_osx_dynamic.dylib") - } - return false - }) + XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=address"))) } do { @@ -2224,12 +2205,7 @@ final class SwiftDriverTests: XCTestCase { let linkJob = plannedJobs[2] let linkCmd = linkJob.commandLine - XCTAssertTrue(linkCmd.contains { - if case .path(let path) = $0 { - return path.name.contains("darwin/libclang_rt.tsan_osx_dynamic.dylib") - } - return false - }) + XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=thread"))) } do { @@ -2245,12 +2221,7 @@ final class SwiftDriverTests: XCTestCase { let linkJob = plannedJobs[2] let linkCmd = linkJob.commandLine - XCTAssertTrue(linkCmd.contains { - if case .path(let path) = $0 { - return path.name.contains("darwin/libclang_rt.ubsan_osx_dynamic.dylib") - } - return false - }) + XCTAssertTrue(linkCmd.contains(.flag("-fsanitize=undefined"))) } // FIXME: This test will fail when run on macOS, because the driver uses @@ -2399,7 +2370,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertTrue(matchTemporary(plannedJobs[1].outputs.first!.file, "foo3.o")) XCTAssertEqual(plannedJobs[2].outputs.count, 3) XCTAssertTrue(matchTemporary(plannedJobs[2].outputs.first!.file, "foo5.o")) - XCTAssertTrue(plannedJobs[3].tool.name.contains(driver1.targetTriple.isDarwin ? "ld" : "clang")) + XCTAssertTrue(plannedJobs[3].tool.name.contains("clang")) XCTAssertEqual(plannedJobs[3].outputs.count, 1) XCTAssertEqual(plannedJobs[3].outputs.first!.file, VirtualPath.relative(RelativePath(executableName("Test")))) } @@ -3345,10 +3316,8 @@ final class SwiftDriverTests: XCTestCase { XCTAssert(plannedJobs[0].commandLine.contains(.flag("x86_64-apple-macosx10.14"))) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssertTrue(plannedJobs[1].commandLine.contains(subsequence: [ - "-platform_version", "mac-catalyst", "13.1.0"])) - XCTAssertTrue(plannedJobs[1].commandLine.contains(subsequence: [ - "-platform_version", "macos", "10.14.0"])) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("--target=x86_64-apple-ios13.1-macabi"))) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-darwin-target-variant=x86_64-apple-macosx10.14"))) } // Test -target-variant is passed to generate pch job @@ -3372,10 +3341,8 @@ final class SwiftDriverTests: XCTestCase { XCTAssert(plannedJobs[1].commandLine.contains(.flag("x86_64-apple-macosx10.14"))) XCTAssertEqual(plannedJobs[2].kind, .link) - XCTAssertTrue(plannedJobs[2].commandLine.contains(subsequence: [ - "-platform_version", "mac-catalyst", "13.1.0"])) - XCTAssertTrue(plannedJobs[2].commandLine.contains(subsequence: [ - "-platform_version", "macos", "10.14.0"])) + XCTAssert(plannedJobs[2].commandLine.contains(.flag("--target=x86_64-apple-ios13.1-macabi"))) + XCTAssert(plannedJobs[2].commandLine.contains(.flag("-darwin-target-variant=x86_64-apple-macosx10.14"))) } } @@ -3655,7 +3622,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_osx.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } do { @@ -3667,8 +3634,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_ios.a")) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_iossim.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } do { @@ -3680,7 +3646,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_ios.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } do { @@ -3692,8 +3658,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_tvos.a")) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_tvossim.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } do { @@ -3705,7 +3670,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_tvos.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } do { @@ -3717,8 +3682,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_watchos.a")) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_watchossim.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } do { @@ -3730,7 +3694,7 @@ final class SwiftDriverTests: XCTestCase { XCTAssertEqual(plannedJobs[0].kind, .compile) XCTAssertEqual(plannedJobs[1].kind, .link) - XCTAssert(plannedJobs[1].commandLine.containsPathWithBasename("libclang_rt.profile_watchos.a")) + XCTAssert(plannedJobs[1].commandLine.contains(.flag("-fprofile-generate"))) } // FIXME: This will fail when run on macOS, because @@ -3794,11 +3758,7 @@ final class SwiftDriverTests: XCTestCase { func testToolsDirectory() throws { try withTemporaryDirectory { tmpDir in -#if os(iOS) || os(macOS) || os(tvOS) || os(watchOS) - let ld = tmpDir.appending(component: "ld") -#else let ld = tmpDir.appending(component: executableName("clang")) -#endif // tiny PE binary from: https://archive.is/w01DO let contents: [UInt8] = [ 0x4d, 0x5a, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x4c, 0x01, 0x01, 0x00, @@ -3902,12 +3862,9 @@ final class SwiftDriverTests: XCTestCase { ])) } XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("macos"), - .flag("10.14.0"), - .flag("10.15.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-macosx10.14"))) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--sysroot"))) + XCTAssertTrue(frontendJobs[1].commandLine.containsPathWithBasename(sdk1.basename)) } do { @@ -3928,16 +3885,8 @@ final class SwiftDriverTests: XCTestCase { .flag("13.1"), ])) XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("macos"), - .flag("10.14.0"), - .flag("10.15.0"), - .flag("-platform_version"), - .flag("mac-catalyst"), - .flag("13.1.0"), - .flag("13.1.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-macosx10.14"))) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("-darwin-target-variant=x86_64-apple-ios13.1-macabi"))) } do { @@ -3961,16 +3910,8 @@ final class SwiftDriverTests: XCTestCase { ])) } XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("macos"), - .flag("10.14.0"), - .flag("10.15.4"), - .flag("-platform_version"), - .flag("mac-catalyst"), - .flag("13.1.0"), - .flag("13.4.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-macosx10.14"))) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("-darwin-target-variant=x86_64-apple-ios13.1-macabi"))) } do { @@ -3991,16 +3932,8 @@ final class SwiftDriverTests: XCTestCase { .flag("10.15.4") ])) XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("mac-catalyst"), - .flag("13.1.0"), - .flag("13.4.0"), - .flag("-platform_version"), - .flag("macos"), - .flag("10.14.0"), - .flag("10.15.4"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-ios13.1-macabi"))) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("-darwin-target-variant=x86_64-apple-macosx10.14"))) } } } @@ -4070,11 +4003,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("macos"), - .flag("10.15.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-macos10.15"))) } // Mac gained aarch64 support in v11 @@ -4086,11 +4015,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("macos"), - .flag("11.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=arm64-apple-macos10.15"))) } // Mac Catalyst on x86_64 was introduced in v13. @@ -4102,11 +4027,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("mac-catalyst"), - .flag("13.1.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-ios12.0-macabi"))) } // Mac Catalyst on arm was introduced in v14. @@ -4118,11 +4039,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("mac-catalyst"), - .flag("14.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=aarch64-apple-ios12.0-macabi"))) } // Regular iOS @@ -4134,11 +4051,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("ios"), - .flag("12.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=aarch64-apple-ios12.0"))) } // Regular tvOS @@ -4150,11 +4063,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("tvos"), - .flag("12.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=aarch64-apple-tvos12.0"))) } // Regular watchOS @@ -4166,11 +4075,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("watchos"), - .flag("6.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=aarch64-apple-watchos6.0"))) } // x86_64 iOS simulator @@ -4182,11 +4087,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("ios-simulator"), - .flag("12.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=x86_64-apple-ios12.0-simulator"))) } // aarch64 iOS simulator @@ -4198,11 +4099,7 @@ final class SwiftDriverTests: XCTestCase { let frontendJobs = try driver.planBuild() XCTAssertEqual(frontendJobs[1].kind, .link) - XCTAssertTrue(frontendJobs[1].commandLine.contains(subsequence: [ - .flag("-platform_version"), - .flag("ios-simulator"), - .flag("14.0.0"), - ])) + XCTAssertTrue(frontendJobs[1].commandLine.contains(.flag("--target=aarch64-apple-ios12.0-simulator"))) } } @@ -4439,7 +4336,7 @@ final class SwiftDriverTests: XCTestCase { var output = "" serializer.writeDOT(to: &output) - let linkerDriver = driver.targetTriple.isDarwin ? executableName("ld") : executableName("clang") + let linkerDriver = executableName("clang") if driver.targetTriple.objectFormat == .elf { XCTAssertEqual(output, """ @@ -4955,7 +4852,7 @@ final class SwiftDriverTests: XCTestCase { var driver = try Driver(args: ["swiftc", "foo.swift", "-lto=llvm-thin", "-target", "x86_64-apple-macos11.0"]) let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.map(\.kind), [.compile, .link]) - XCTAssertTrue(plannedJobs[1].commandLine.contains("-lto_library")) + XCTAssertTrue(plannedJobs[1].commandLine.contains("-flto=thin")) } do { @@ -4963,15 +4860,15 @@ final class SwiftDriverTests: XCTestCase { let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.map(\.kind), [.compile, .link]) XCTAssertFalse(plannedJobs[0].commandLine.contains(.path(try VirtualPath(path: "/foo/libLTO.dylib")))) - XCTAssertTrue(plannedJobs[1].commandLine.contains("-lto_library")) - XCTAssertTrue(plannedJobs[1].commandLine.contains(.path(try VirtualPath(path: "/foo/libLTO.dylib")))) + XCTAssertTrue(plannedJobs[1].commandLine.contains("-flto=thin")) + XCTAssertTrue(plannedJobs[1].commandLine.contains(.joinedOptionAndPath("-Wl,-lto_library,", try VirtualPath(path: "/foo/libLTO.dylib")))) } do { var driver = try Driver(args: ["swiftc", "foo.swift", "-lto=llvm-full", "-target", "x86_64-apple-macos11.0"]) let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.map(\.kind), [.compile, .link]) - XCTAssertTrue(plannedJobs[1].commandLine.contains("-lto_library")) + XCTAssertTrue(plannedJobs[1].commandLine.contains("-flto=full")) } do { @@ -4979,15 +4876,16 @@ final class SwiftDriverTests: XCTestCase { let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.map(\.kind), [.compile, .link]) XCTAssertFalse(plannedJobs[0].commandLine.contains(.path(try VirtualPath(path: "/foo/libLTO.dylib")))) - XCTAssertTrue(plannedJobs[1].commandLine.contains("-lto_library")) - XCTAssertTrue(plannedJobs[1].commandLine.contains(.path(try VirtualPath(path: "/foo/libLTO.dylib")))) + XCTAssertTrue(plannedJobs[1].commandLine.contains("-flto=full")) + XCTAssertTrue(plannedJobs[1].commandLine.contains(.joinedOptionAndPath("-Wl,-lto_library,", try VirtualPath(path: "/foo/libLTO.dylib")))) } do { var driver = try Driver(args: ["swiftc", "foo.swift", "-target", "x86_64-apple-macos11.0"]) let plannedJobs = try driver.planBuild() XCTAssertEqual(plannedJobs.map(\.kind), [.compile, .link]) - XCTAssertFalse(plannedJobs[1].commandLine.contains("-lto_library")) + XCTAssertFalse(plannedJobs[1].commandLine.contains("-flto=thin")) + XCTAssertFalse(plannedJobs[1].commandLine.contains("-flto=full")) } #endif }