Experimenting with concurrency: linker can't find /usr/lib/swift/libswift_Concurrency.dylib

I'm trying to experiment with the new concurrency APIs, but I'm getting a linker error on macOS.

I'm on macOS 10.15.7 with Xcode 12.2.

I installed the swift-DEVELOPMENT-SNAPSHOT-2020-11-17-a toolchain.

I created a new SwiftPM executable package and put this code in main.swift:

func computeInt() async -> Int {
  return 42
}

let task = Task.runDetached {
  let answer = await computeInt()
  print(answer)
}

Then I run it like this:

swift run \
  --toolchain /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-11-17-a.xctoolchain/ \
  -Xswiftc -Xfrontend -Xswiftc -enable-experimental-concurrency

This compiles, but I'm getting a linker error because the linker is looking for /usr/lib/swift/libswift_Concurrency.dylib, which obviously doesn't exist:

[3/3] Linking AsyncAwait
dyld: Library not loaded: /usr/lib/swift/libswift_Concurrency.dylib
  Referenced from: /Users/elo/code/AsyncAwait/.build/x86_64-apple-macosx/debug/AsyncAwait
  Reason: image not found

How can I tell the linker to look for libswift_Concurrency in the toolchain directory?

By the way, I'm getting the same results when building from an Xcode command line project. I can run the SwiftPM package on Linux (tested in a Docker container using the swiftlang/swift:nightly-focal image).

This looks like an @rpath issue. One workaround should be:

install_name_tool -rpath /usr/lib/swift /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-11-17-a.xctoolchain/ /Users/elo/code/AsyncAwait/.build/x86_64-apple-macosx/debug/AsyncAwait

which changes the @rpath from the system to the path in the toolchain for this specific application. There's probably a Swift flag somewhere that can be set to change the @rpath of the resulting executable.

1 Like

It looks like you're expected to set DYLD_LIBRARY_PATH to test with the set of Swift libraries in a toolchain. See https://github.com/apple/swift/pull/34216

1 Like

Thanks for the tip, Joe, I hadn't seen that PR. It sounds like it should work, but it doesn't for me, I'm still getting the same error:

$ echo $DYLD_LIBRARY_PATH
/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-11-17-a.xctoolchain/usr/lib/swift/macosx

$ xcrun --toolchain org.swift.50202011171a \
  swift run \
    -Xswiftc -Xfrontend -Xswiftc -enable-experimental-concurrency
dyld: Library not loaded: /usr/lib/swift/libswift_Concurrency.dylib
  Referenced from: /Users/elo/code/AsyncAwait/.build/x86_64-apple-macosx/debug/AsyncAwait
  Reason: image not found

(I tried using swift run --toolchain … instead of xcrun --toolchain … swift run, with the same result.)

Thank you too, Alejandro. Your idea didn't work right away, but it got me on the right track. Turns out that the toolchain's lib/swift directory is present in my executable's @rpath (I checked this with otool -l). But here's otool -L for the executable, showing that libswift_Concurrency.dylib doesn't use @rpath and is hardcoded to /usr/lib/swift instead:

otool -L .build/x86_64-apple-macosx/debug/AsyncAwait
.build/x86_64-apple-macosx/debug/AsyncAwait:
	/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1770.106.0)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.0.0)
	/System/Library/Frameworks/CFNetwork.framework/Versions/A/CFNetwork (compatibility version 1.0.0, current version 1207.0.0)
	/usr/lib/swift/libswift_Concurrency.dylib (compatibility version 1.0.0, current version 0.0.0)
	@rpath/libswiftCore.dylib (compatibility version 1.0.0, current version 0.0.0)
	@rpath/libswiftCoreFoundation.dylib (compatibility version 1.0.0, current version 0.0.0, weak)
	@rpath/libswiftCoreGraphics.dylib (compatibility version 1.0.0, current version 0.0.0, weak)
	@rpath/libswiftDarwin.dylib (compatibility version 1.0.0, current version 0.0.0, weak)
	@rpath/libswiftDispatch.dylib (compatibility version 1.0.0, current version 0.0.0)
	@rpath/libswiftFoundation.dylib (compatibility version 1.0.0, current version 0.0.0)
	@rpath/libswiftIOKit.dylib (compatibility version 1.0.0, current version 1.0.0, weak)
	@rpath/libswiftObjectiveC.dylib (compatibility version 1.0.0, current version 0.0.0, weak)
	@rpath/libswiftSwiftOnoneSupport.dylib (compatibility version 1.0.0, current version 0.0.0)
	@rpath/libswiftXPC.dylib (compatibility version 1.0.0, current version 1.1.0, weak)

I was able to fix the path with this command:

 install_name_tool -change \
  /usr/lib/swift/libswift_Concurrency.dylib \
  /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2020-11-17-a.xctoolchain/usr/lib/swift/macosx/libswift_Concurrency.dylib \ 
  .build/x86_64-apple-macosx/debug/AsyncAwait

Is it a bug that libswift_Concurrency.dylib isn't linked using @rpath?

Does it work if you build a binary then execute it with DYLD_LIBRARY_PATH set? I wonder if the toolchains build with library validation or other security flags set on the swift binary that might cause the interpreter to disregard DYLD_LIBRARY_PATH.

1 Like

Yeah, that works! I can't say I understand why, but thanks!

Terms of Service

Privacy Policy

Cookie Policy