-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[cmake] Copy Dispatch to the SDK subdir on host. #37231
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
Conversation
041f305
to
efcd83e
Compare
copy libdispatch to a subdir sounds counter-intuitive. should it not be a normal dependency on linux like any library? |
We are in a bit of a rock and a hard place here. AIUI, the Unixlike toolchains specify rpath as Compiled binaries don't have direct dependencies on libdispatch, but do have implicit dependencies transitively through On Linux, the loader apparently doesn't just look at the rpath, but subdirectories of the rpath named Elsewhere, e.g., on OpenBSD (at least), no rpath subdirectories are searched. The loader picks the version of One alternative for us is to force the rpath to the
So ultimately, do we want to copy the dependency twice, or hack the rpath in the invocation? A rock and a hard place. Or is something else entirely that I haven't thought of? |
Actually, hacking the rpath in the invocation is wrong. When building the toolchain (not just swift in isolation), the The question remains: why are we putting the Dispatch libraries in |
We have two directories for Swift libraries, * `SWIFT_SDK_<platform>_LIB_SUBDIR`, a.k.a., the SDK subdir, a.k.a., `swift-<platform>-<arch>/lib/swift/<platform>`, and * `SWIFTLIB_SINGLE_SUBDIR`, a.k.a., `swift-<platform>-<arch>/lib/swift/<platform>/<arch>`. Through the Swift build, libraries are emitted to both `.../lib/swift/<platform>` and `.../lib/swift/<platform>/<arch>`. However, when building toolchains, only `.../lib/swift/<platform>/` is populated with libraries. None of this normally isn't a problem; the Swift libraries do not have inherent interdependencies. This however changes with Concurrency: Concurrency has an implicit dependency on libdispatch. When Swift is built, we have two copies of `libswift_Concurrency.so`: one in `.../lib/swift/<platform>` and one in `.../lib/swift/<platform>/<arch>`. Prior to this commit, we unconditionally copy `libdispatch.so` and `libBlocksRuntime.so` to only _one_ place -- that is, `.../lib/swift/<platform>/<arch>`. swiftc emits binaries on ELF systems with an rpath of `.../lib/swift/<platform>`. These binaries implicitly import Concurrency, so they link against `libswift_Concurrency.so` (whether they use Concurrency features or not). The library's `$ORIGIN` is searched to find `libdispatch.so`. Now, nothing breaks on Linux because there the loader, when given an rpath, searches both `.../lib/swift/<platform>` and `.../lib/swift/<platform>/<arch>` even though the rpath only specifies one directory.. However, on other platforms, only the given rpath is searched. `libdispatch.so` does not reside next to `libswift_Concurrency.so` because it has been copied to `.../lib/swift/<platform>/<arch>`; not in the rpath. There are a few ways to solve this: change the way rpaths are configured, only emit libraries into one place, copy `libdispatch.so` only to the path matching the rpath, or copy `libdispatch.so` wherever `libswift_Concurrency.so` is copied, Because the toolchain file layout is different to the file layout when only Swift is built, hacking the rpath is brittle. Presumably, the reason why we have a `libswift_Concurrency.so` residing in two places is to support builds where multiple architectures are supported in the one build directory, so we cannot just copy `libdispatch.so` _only_ to `.../lib/swift/<platform>`. Ultimately, We need to ensure that every instance where `libswift_Concurrency.so` can be used has `libdispatch.so` residing next to it, which we do here. Note that this implicit dependency resolution would not happen unless we added a `-ldispatch` flag to make this all work, but other platforms are instaed using `$ORIGIN` to get the search to work properly, so we also do this for OpenBSD in this commit.
I think the goal is to move everything to If you're having issues with libdispatch not installed to the latter path, maybe it should be installed there too on OpenBSD, dunno? |
Cool, sounds like my guess is correct.
Right. I'm just testing an update to this PR (not pushed yet) that copies libdispatch everywhere libswift_Concurrency.so resides (so unfortunately, we have to go from two copies to four copies always), because that is ultimately what is required. |
efcd83e
to
c0c93fa
Compare
Okay, now this PR unconditionally makes four copies. This means that whichever library the platform loader picks, it can always resolve its libdispatch dependency. |
Ping. |
@drexin, you added this libdispatch build file, could you review? |
@swift-ci test |
We have two directories for Swift libraries,
SWIFT_SDK_<platform>_LIB_SUBDIR
, a.k.a., the SDK subdir,a.k.a.,
swift-<platform>-<arch>/lib/swift/<platform>
, andSWIFTLIB_SINGLE_SUBDIR
,a.k.a.,
swift-<platform>-<arch>/lib/swift/<platform>/<arch>
.We unconditionally copy libdispatch.so and libBlocksRuntime.so to
SWIFTLIB_SINGLE_SUBDIR. But this is insufficient, because swiftc emits
binaries with an RPATH with the SDK subdir.
This does not cause problems when these libraries are installed on the
platform itself, but the platform loader will choke since it can't find
those libraries -- as they are not in the RPATH.
This itself isn't so much of an issue, but it is an inconsistency since
we normally do the needful to ensure we don't need to install binaries
and libraries to the system to run and execute the Swift compiler and
binaries, so this is indeed something of a regression.
Normally, we would require adding a
-ldispatch
flag to make this allwork but this is difficult to do correctly, and more
importantly because other platforms are using
$ORIGIN
to get thedependency search to work properly, let's do so also here.
This seems like the best way to do this; please advise if there is some
better mechanism to go about achieving this goal.