-
Notifications
You must be signed in to change notification settings - Fork 10.5k
SR-7724: Build SourceKit libdispatch into its own directory #19640
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
This is a partial fix for https://bugs.swift.org/browse/SR-7724
mmm, no, it doesn't really overlap with it, but does conflict with it. I'm not sure I understand the cycle here though. If libdispatch is built here, it is actually built after the standard library, but before SourceKit, so there is a total ordering which does allow it to be built just once. Can you explain how build-script breaks that? |
@compnerd build-script always calls rm -fr on the libdispatch build dir when it's asked to build libdispatch (with --libdispatch). It also configures it with different flags into the same build dir. So the usual build order on a clean checkout on Linux is currently:
So SourceKit winds up linked to a libdispatch that was configured by CMake ExternalProject, which is not included in the package but instead blown away and rebuilt by build-script. This PR doesn't change that, but creates a separate build directory for the sourcekit-libdispatch so that build-script can drop the rm -fr. Does that make sense? |
Sure, I get that. @gottesmm - do you remember why we had to restore the |
@compnerd Question, isn't that something that is fixed by using @llvm-beanz's stuff from LLVM that wraps external project? Swift depends on LLVM's cmake. It should be ok to use those and if they solve the dependency stuff for us even better. |
@compnerd I don't understand how this change conflicts with #19639. Is the goal that ExternalProject subsumes build-script? SourceKit without stdlib or swiftDispatch seems like an uncommon build configuration to support compared to SourceKit+stdlib+swiftDispatch. Right now sourcekit will be linked against a differently-configured libdispatch than the one that's ultimately installed on the system |
@gottesmm - hmm, possibly. In either case, we should look at wrapping up LLVM's ExternalProject wrapper as it would simplify the CMake logic in swift. @kevints - yes, the longer term plan is to remove build-script entirely and have CMake orchestrate the builds with inter-project dependency tracking. The last piece I think that is left is my work to switch s-c-f to CMake from the python based build. Once that is done, I believe that all the components can be wired up using CMake. |
@compnerd got it. any reason we can't use a separate build directory for sourcekit-dispatch while we still have 2 builds though? |
<INSTALL_DIR>/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}/${CMAKE_SHARED_LIBRARY_PREFIX}dispatch${CMAKE_SHARED_LIBRARY_SUFFIX} | ||
<INSTALL_DIR>/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}/${SWIFT_HOST_VARIANT_ARCH}/Dispatch.swiftmodule | ||
<INSTALL_DIR>/lib/swift/${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}/${SWIFT_HOST_VARIANT_ARCH}/Dispatch.swiftdoc | ||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "Finished building libdispatch for SourceKit" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to have an echo that occurs afterwards, please keep the installation in the same command. I don't think that we should have the build install the components.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I should have mentioned this strange construct in a comment - cmake 3.5.3 doesn't have an INSTALL_BYPRODUCTS list for ExternalProject_Add so file-level dependencies don't work as they should with ninja (I want to depend on the "installed" location of libdispatch rather than the built one). But it also doesn't like having an empty INSTALL_COMMAND (which I why I added the echo here).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran into issues with the dependencies IIRC when I used the installed artifacts. But, if it works, sure, that is fine. However, according to the documentation, https://cmake.org/cmake/help/v3.5/module/ExternalProject.html, 3.5 does include support for BUILD_BYPRODUCTS
.
# NOTE(compnerd) since we do not use target_link_libraries, we do not get | ||
# the implicit dependency tracking. Add an explicit dependency until we can | ||
# use target_link_libraries. | ||
add_dependencies(${target} BlocksRuntime) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this should be removed. This should be adjusted for the new layout right? Or am I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BlocksRuntime is statically linked into libdispatch already so it's not correct to link BlocksRuntime again, this build should be linking dispatch to get BlocksRuntime symbols.
$ readelf --dyn-syms -W swift-4.2-RELEASE-ubuntu14.04/usr/lib/swift/linux/libdispatch.so | grep -E '(Block_copy|Block_release)'
605: 0000000000060220 196 FUNC GLOBAL DEFAULT 11 _Block_release
740: 00000000000600f0 7 FUNC GLOBAL DEFAULT 11 _Block_copy
853: 0000000000060340 201 FUNC GLOBAL DEFAULT 11 _Block_copy_collectable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is statically linked, but the symbols are not supposed to be re-exported. This is something that I can look into fixing: see #17451 and swiftlang/swift-corelibs-libdispatch#362. This actually is a bigger issue where the blocks usage breaks down :-(. Seems like I made a mistake in the libdispatch build? I'll take a look at that as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should only be one copy of BlocksRuntime in the entire program. For example dispatch_async calls Block_copy
and Block_release
on the blocks that are passed to it. A program can also call these functions on the same block objects you pass to dispatch_async; if they are different you risk undefined behavior. So BlocksRuntime is really a public part of the libdispatch ABI and statically linking it into dispatch re-exporting its symbols isn't possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed that there should be a single copy, which is why we need the shared build of it for other targets as well and that was the motivation for the original change that I got distracted from. I suppose it is high time that I revisit that.
I really think that exporting it as part of libdispatch is fundamentally the wrong approach. You can use block with C, and in such a scenario, you shouldn't pull in libdispatch. I think it is better to actually fix the build so that we build BlocksRuntime shared and use that appropriately.
@gottesmm, I think that we could do that with CMake caches (it works great!), but thats a separate consideration. @kevints, I think that I can see an argument for two different builds - one is the tool host and one is the target. So, I think that if we want to do this in a separate directory, that does make some sense, but then we should configure it the same was as the host tools. |
@@ -96,28 +96,33 @@ if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") | |||
ExternalProject_Add(libdispatch | |||
SOURCE_DIR | |||
"${SWIFT_PATH_TO_LIBDISPATCH_SOURCE}" | |||
BINARY_DIR | |||
"${SWIFT_PATH_TO_LIBDISPATCH_BUILD}" | |||
CMAKE_ARGS | |||
-DCMAKE_C_COMPILER=${PATH_TO_CLANG_BUILD}/bin/clang | |||
-DCMAKE_CXX_COMPILER=${PATH_TO_CLANG_BUILD}/bin/clang++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, if we know that this build is for the host, we should also use the same compiler that we used to build swiftc no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SourceKit is logically a part of the toolchain, so we should use the same build settings for it. This means (I think) that we should use the host libdispatch if one is available or build a toolchain-specific copy. This copy would need to be installed somewhere that it doesn't conflict with the runtime's copy in the common case that the host and target are the same, so disabling the swift overlay in this build seems like a non-starter.
This complexity isn't present on Darwin platforms as the swift overlay for Dispatch is built into a separate library (libswiftDispatch.dylib). Perhaps we should explore this approach for Linux as well, since that would allow us to have libsourcekitdInProc.so, libdispatch.so and libswiftDispatch.so installed side-by-side with SourceKit having no dependency on the swift runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, thinking more about this, I think that you are correct in that we need a libdispatch for the toolchain.
I definitely agree on the libdispatch swift SDK overlay being split out on Linux and Windows much like Darwin. This gives us uniform behaviour as well as gives us the ability to break some of that cycle.
INTERFACE_INCLUDE_DIRECTORIES | ||
${install_dir}/include | ||
IMPORTED_LINK_INTERFACE_LIBRARIES | ||
swiftCore-${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_LIB_SUBDIR}-${SWIFT_HOST_VARIANT_ARCH}) | ||
|
||
add_library(BlocksRuntime STATIC IMPORTED) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The removal of BlocksRuntime
is actually problematic for Windows builds, since we need that to enable SourceKit builds as well. Ideally, we would use a shared BlocksRuntime, but, that can be handled separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still can't test on Windows, but at least on Linux the implementation of BlocksRuntime seems to live in libdispatch, so SourceKit should link that:
$ readelf --dyn-syms -W swift-4.2-RELEASE-ubuntu14.04/usr/lib/swift/linux/libdispatch.so | grep -E '(Block_copy|Block_release)'
605: 0000000000060220 196 FUNC GLOBAL DEFAULT 11 _Block_release
740: 00000000000600f0 7 FUNC GLOBAL DEFAULT 11 _Block_copy
853: 0000000000060340 201 FUNC GLOBAL DEFAULT 11 _Block_copy_collectable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bug :-) It shouldn't be exposed from libdispatch. The static linkage shouldnt expose the symbols (which is part of the problem) - you cant actually use blocks without the shared runtime as John and I discussed on swiftlang/swift-corelibs-libdispatch#362. I think that I'm going to try to get a couple of my patches up and then look into that again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure you can - for the simple reason that you can call Block_copy
and Block_release
from outside of dispatch on objects you pass to dispatch. @rjmccall 's statement in
swiftlang/swift-corelibs-libdispatch#362 (comment) seems a far cry from "yes, it definitely works". AIUI, at best it might work if the implementations the program and the dispatch library can see are ABI compatible, but the best way to ensure that IMO is just to use the same definition in the first place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the same definition would be through a shared library (which is what the PR was working towards). I'm just saying that in the mean time, statically linking against it should get you unblocked right?
FYI, after seeing this PR and thinking more about it, I ended up going down the same route as you to enable SourceKit on Windows, but, I think that I want to address the BlocksRuntime issue as well. If we get the BlocksRuntime built with hidden visibility and linked in, would it unblock you? I do realize that it is broken in terms of support, but, I think that fixing BlocksRuntime to be shared is the right approach for that, and we can look at that separate of this PR. I'm just trying to determine if you want to help look at that first or if you want to try to get this change patched up and merged first. |
This is a partial fix for https://bugs.swift.org/browse/SR-7724. It changes the Swift build system to place the libdispatch that SourceKit is linked to in a different directory. This is still not ideal (SourceKit should link the same version of dispatch swift apps will link at runtime) but there's a dependency cycle between swift and corelibs-libdispatch (at least the way build-script is currently structured). A future change can reduce the number of dispatch build directories from 2 to 1. This change is still valuable because it restores the ability to incrementally build libdispatch when calling build-script.
Partially resolves SR-7724.