I am developing a command line app in Swift which will call out to swift in order to initialize packages, compile things, test things, etc. I am using the swift package manager and Xcode. In my tool, I call swift from a Process. If I am running my tool from the command line, this works fine. However, if I am running my tool from Xcode, some strange things are printed to standard error. In particular, I get

Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift for reading: Too many levels of symbolic links

What is causing this? Is there some way I can avoid it, or can I just not run/test this utility from Xcode?

Here are reproduction steps:

mkdir XcodeRedirectionTest
cd XcodeRedirectionTest
swift package init
open Package.swift

Then in Tests/XcodeRedirectionTestTests/XcodeRedirectionTestTests.swift, paste

import XCTest

final class XcodeRedirectionTestTests: XCTestCase {
    func testExample() {
        let process = Process()
        process.launchPath = "/usr/bin/swift"
        process.arguments = ["--version"]

        let standardOutput = Pipe()
        let standardError = Pipe()

        process.standardOutput = standardOutput
        process.standardError = standardError

        process.launch()
        process.waitUntilExit()

        guard let output = String(data: standardOutput.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) else { XCTFail(); return }
        guard let error = String(data: standardError.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8) else { XCTFail(); return }

        XCTAssertEqual(process.terminationReason, .exit)
        XCTAssertEqual(process.terminationStatus, 0)
        XCTAssertEqual(error, "")
        XCTAssert(output.starts(with: "Apple Swift version 5.4"))
    }
}

Testing in Xcode fails with

file://.../XcodeRedirectionTest/Tests/XcodeRedirectionTestTests/XcodeRedirectionTestTests.swift: test failure: XcodeRedirectionTestTests.testExample() failed: XCTAssertEqual failed: ("2021-05-18 19:43:18.084463-0400 swift[2836:4100702] Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift for reading: Too many levels of symbolic links
") is not equal to ("")

That is (so you don't have to scroll (as much)), the standard error ends up being

Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift for reading: Too many levels of symbolic links

However, running swift test from the command line succeeds. No standard error!

If it matters, I am running Xcode 12.5 on macOS Big Sur 11.2.3.

1

There are 1 answers

1
deaton.dg On

I was able to narrow this down to the environment variable OS_ACTIVITY_DT_MODE. It seems that Xcode sets this to 1 when running programs. If this variable is unset, the error is not displayed. The code I used to accomplish this is

if ProcessInfo.processInfo.environment.keys.contains("OS_ACTIVITY_DT_MODE") {
    var env = ProcessInfo.processInfo.environment
    env["OS_ACTIVITY_DT_MODE"] = nil
    process.environment = env
}

This requires more testing to understand the relationship between the PWD passed in the environment and Process.currentDirectoryURL, but this at least gets the ball rolling.