Skip to content

Locate "arclite" library relative to the Clang in the active Xcode #581

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion Sources/SwiftDriver/Jobs/DarwinToolchain+LinkerSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import TSCUtility
import SwiftOptions

extension DarwinToolchain {
internal func findXcodeClangPath() throws -> AbsolutePath? {
let result = try executor.checkNonZeroExit(
args: "xcrun", "-toolchain", "default", "-f", "clang",
environment: env
).spm_chomp()

return result.isEmpty ? nil : AbsolutePath(result)
}

internal func findXcodeClangLibPath(_ additionalPath: String) throws -> AbsolutePath? {
let path = try getToolPath(.swiftCompiler)
.parentDirectory // 'swift'
Expand All @@ -24,7 +33,7 @@ extension DarwinToolchain {

// If we don't have a 'lib/arc/' directory, find the "arclite" library
// relative to the Clang in the active Xcode.
if let clangPath = try? getToolPath(.clang) {
if let clangPath = try? findXcodeClangPath() {
return clangPath
.parentDirectory // 'clang'
.parentDirectory // 'bin'
Expand Down
4 changes: 4 additions & 0 deletions Sources/SwiftDriver/Toolchains/DarwinToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,14 @@ import SwiftOptions
targetTriple: Triple,
targetVariantTriple: Triple?,
diagnosticsEngine: DiagnosticsEngine) throws {
// On non-darwin hosts, libArcLite won't be found and a warning will be emitted
// Guard for the sake of tests runnin on all platforms
#if os(macOS)
// Validating arclite library path when link-objc-runtime.
validateLinkObjcRuntimeARCLiteLib(&parsedOptions,
targetTriple: targetTriple,
diagnosticsEngine: diagnosticsEngine)
#endif
// Validating apple platforms deployment targets.
try validateDeploymentTarget(&parsedOptions, targetTriple: targetTriple)
if let targetVariantTriple = targetVariantTriple,
Expand Down
47 changes: 47 additions & 0 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,8 @@ final class SwiftDriverTests: XCTestCase {

do {
// static linking
// Locating relevant libraries is dependent on being a macOS host
#if os(macOS)
var driver = try Driver(args: commonArgs + ["-emit-library", "-static", "-L", "/tmp", "-Xlinker", "-w", "-target", "x86_64-apple-macosx10.9", "-lto=llvm-full"], env: env)
let plannedJobs = try driver.planBuild()

Expand Down Expand Up @@ -1161,6 +1163,7 @@ final class SwiftDriverTests: XCTestCase {
XCTAssertFalse(cmd.contains("-lto_library"))
XCTAssertFalse(cmd.contains("-syslibroot"))
XCTAssertFalse(cmd.contains("-no_objc_category_merging"))
#endif
}

do {
Expand All @@ -1186,12 +1189,15 @@ final class SwiftDriverTests: XCTestCase {

do {
// lto linking
// Locating relevant libraries is dependent on being a macOS host
#if os(macOS)
var driver1 = try Driver(args: commonArgs + ["-emit-executable", "-target", "x86_64-apple-macosx10.15", "-lto=llvm-thin"], env: env)
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")))
#endif

var driver2 = try Driver(args: commonArgs + ["-emit-executable", "-target", "x86_64-unknown-linux", "-lto=llvm-thin"], env: env)
let plannedJobs2 = try driver2.planBuild()
Expand Down Expand Up @@ -1436,6 +1442,18 @@ final class SwiftDriverTests: XCTestCase {
}
}

private func clangPathInActiveXcode() throws -> AbsolutePath? {
#if !os(macOS)
return nil
#endif
let process = Process(arguments: ["xcrun", "-toolchain", "default", "-f", "clang"])
try process.launch()
let result = try process.waitUntilExit()
guard result.exitStatus == .terminated(code: EXIT_SUCCESS) else { return nil }
guard let path = String(bytes: try result.output.get(), encoding: .utf8) else { return nil }
return path.isEmpty ? nil : AbsolutePath(path.spm_chomp())
}

func testCompatibilityLibs() throws {
var env = ProcessEnv.vars
env["SWIFT_DRIVER_TESTS_ENABLE_EXEC_PATH_FALLBACK"] = "1"
Expand Down Expand Up @@ -1537,6 +1555,30 @@ 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
}
}

Expand Down Expand Up @@ -2341,7 +2383,10 @@ final class SwiftDriverTests: XCTestCase {
return
}
}
// On non-darwin hosts, libArcLite won't be found and a warning will be emitted
#if os(macOS)
try assertNoDriverDiagnostics(args: "swiftc", "-c", "-target", "x86_64-apple-macosx10.14", "-link-objc-runtime", "foo.swift")
#endif
}

func testProfileArgValidation() throws {
Expand Down Expand Up @@ -3445,6 +3490,7 @@ final class SwiftDriverTests: XCTestCase {
}

func testLTOLibraryArg() throws {
#if os(macOS)
do {
var driver = try Driver(args: ["swiftc", "foo.swift", "-lto=llvm-thin", "-target", "x86_64-apple-macos11.0"])
let plannedJobs = try driver.planBuild()
Expand All @@ -3463,6 +3509,7 @@ final class SwiftDriverTests: XCTestCase {
XCTAssertEqual(plannedJobs.map(\.kind), [.compile, .link])
XCTAssertFalse(plannedJobs[1].commandLine.contains("-lto_library"))
}
#endif
}

func testBCasTopLevelOutput() throws {
Expand Down