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
[SR-397] Linux - module using <dispatch/dispatch.h> does not compile cleanly with "swift build" #5437
Comments
I'm going to PR the solution above. |
It looks like this has been PRed and closed before under #75. I'm going to resurrect this discussion on the list; clearing assignment for now. |
I have resurrected this idea under PR #107. If that PR is merged, we can say otherCompilerOptions: ["-Xcc", "-fblocks"] to work around this issue. |
We should just add this to the compiler. However, I think we were hoping to establish a different blocks ABI on Linux, so that we can at least use Swift's retain-counting on them instead of Objective-C's. |
So, to be clear, `-fblocks` is required for anything that links to `CDispatch`? |
It may be possible to use dispatch without blocks (the _f functions), but it's not something I really care about supporting in Swift. |
Comment by Tom Sheffler (JIRA) This issue is actually pretty subtle. At the present time, there is probably only one C module anywhere that provides a header file with blocks – and that is libdispatch. Expanding the module mechanism to handle this one case may be overkill. On the other hand, it blocked me. So already it's a small issue. Perhaps there could be support for a "good" way to make modules, and a "messy" way ... that is more akin to using clang to create a library, but requires the programmer to create a Makefile or recipe. Even a well-documented workaround would be ok. In the future there will be a more Swift-y libDispatch, and from the comments here I'm surmising that it will use runtime support different from that of ObjC. |
Comment by Daniel Eggert (JIRA) In my opinion the |
In case you missed it you can now specify `-Xcc` and `-Xlinker` flags to `swift build`. So here you could do `swift build -Xcc -fblocks` |
Comment by Tom Sheffler (JIRA) I verified this against swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a/swift-DEVELOPMENT-SNAPSHOT-2016-01-25-a-ubuntu14.04.tar.gz Using swift build -Xcc -fblocks this example compiles and runs just fine now. |
Comment by Joel Saltzman (JIRA) It mostly works for me. I can't seem to get dispatch_get_specific to compile. I updated the working example project to show my compile errors: root@dec0c641b9ec:/gcd# swift build -Xcc -fblocks |
Comment by Joel Saltzman (JIRA) Old version of libdispatch on Linux 😛 |
In general, most use of libdispatch on Linux should use https://github.com/apple/swift-corelibs-libdispatch. But if I read this correctly, this issue here is about instead using the C API directly. And from s00p3rj03l (JIRA User)'s comment above, it sounds as if this may now work, if the version of `libdispatch` was old? |
Comment by David Grove (JIRA) This issue will be resolved by apple/swift#3835 |
I think in SwiftPM we still need to get -fblocks for C language targets which we build not via |
Looks like libdispatch.so in toolchains is not able to link with C code because of the swift symbols, I couldn't find any other libdispatch binary in the toolchain. $ swift build -Xcc -I/home/ankit/toolchain/usr/lib/swift/ -Xcc -fblocks -Xlinker -L/home/ankit/toolchain/usr/lib/swift/linux -Xlinker -ldispatch
|
I guess we aren't building libdispatch.so separately from the overlay library. dgrove-oss (JIRA User) any opinion on whether it would be nice to be able to build against C libdispatch without the Swift portions? I still think we should probably pass {-fblocks} to C code, so that you can have C code which uses blocks and is linked into something else which uses libdispatch. |
Comment by David Grove (JIRA) That's correct, on Linux we bundle both the core C library and the overlay library into libdispatch.so. My recollection is that we did this intentionally because we don't really want to support the full C API of libdispatch on Linux; just the Swift3 API. das (JIRA User) should verify this. It would not be that hard to restructure the build to produce two shared objects (libcdispatch and libdispatch), but I think it is intentional that we did not do that. |
Comment by Daniel A. Steffen (JIRA) The intentional part is that we don't want to support deprecated C API symbols and private SPI symbols (i.e. *_private.h headers) for either Swift or C clients. Continued support for C clients (and all existing ports & platforms, including macOS) in general is definitely a goal of the project and I'd like us to keep the shared autotools buildsystem working for all such clients. I don't think we have decided either way if that extends to the binaries produced by the swift buildsystem and included in the swift runtime (what support should C code in a swift package be able to expect in general from the fact that Swift is installed ?) Supporting interoperability between C and Swift clients of libdispatch in the same process will almost certainly require a single shared object (both sides need to refer to the same global data structures) |
Comment by David Grove (JIRA) After thinking about it some more, I think the best fix is that if someone is using swift build to link against the C APIs of the libdispatch.so that is provided by the Swift toolchain, we should require them to have the linker arguments: |
Comment by Tom Sheffler (JIRA) Hi dgrove-oss (JIRA User) - earlier you suggested not supporting the full API of dispatch on Linux. I hope you are not suggesting discontinuing the blocks API in libdispatch on Linux. I have a couple of (personal) media projects using blocks in ObjC2/C with libdispatch and it is working really nicely! |
dgrove-oss (JIRA User) I wonder if we could get those to be in the libdispatch module map, so that things would work automatically? |
Comment by David Grove (JIRA) Stepping back, I've lost track of what scenario isn't working now. I think I'm missing the full command line @aciidb0mb3r was trying that was failing to link. If the goal is to support building Swift programs with "swift build" that bypass the Swift3 Dispatch API and instead import CDispatch with block support enabled, that already works for me on Linux with the current Swift toolchain. The module.modulemap for libdispatch in the Swift toolchain defines both Dispatch and CDispatch modules. A Swift program can import the predefined CDispatch module, and the linkage works automatically against the libdispatch.so in the Swift toolchain (and block support is enabled without -Xcc -fblocks on the command line because the header files for dispatch come through the Swift importer). I tested this using an updated gcd4-main.zip example, removing the external definition of CDispatch from Package.swift. Compiles and runs. When this bug was originally opened, we didn't have libdispatch.so or module.modulemap for CDispatch in the Swift toolchain. Now that we do, I don't think we want to support a user using swift build to link against a libdispatch.so that they have built themselves. That will get them into trouble because Foundation and XCTest are linked against the libdispatch that is included in the toolchain and linking against two versions of libdispatch.so will cause problems at runtime. tomsheffler (JIRA User) what I was questioning above was whether or not the libdispatch team at Apple intended to support the usage of libdispatch on Linux beyond its usage as part of Swift. That's not my decision to make – up to them to decide. |
I have a project that depends on libdispatch and not on foundation or xctest. We don't currently build libdispatch separately, but we have an issue open to do it. |
Comment by David Grove (JIRA) @drewcrawford, I'm still missing the big picture. If it is a Swift project (assuming it is, since using swift build), why doesn't importing CDispatch from the Swift toolchain work? Why build libdispatch yourself to use CDispatch from Swift? |
Sorry, I misread your comment. We don't use |
Attachment: Download
Environment
Ubuntu 14.04
Additional Detail from JIRA
md5: 3ce10e8ea99c16ef2da7e8631d663144
is duplicated by:
Issue Description:
While libdispatch is well-supported on Linux, using "Swift Build" for a module wrapping <dispatch/dispatch.h> does not compile cleanly. The problem is that to get all of the features of dispatch, "-fblocks" needs to be specified to Clang, and currently, "swift build" does not enable "-fblocks" for modules that wrap C libraries.
using "swift build" does not include the -fblocks directive
compiling directly with swiftc and including the -fblocks directive works fine
creating a module map that specifies "requires blocks" causes a complaint that Objective-C is not supported
Here is my original report, and a Github repo that illustrates the problem.
I made a module called "CDispatch" with a module.modulemap like this
=======
module CDispatch [system] {
header "/usr/include/dispatch/dispatch.h"
export *
link "dispatch"
}
Then I created a little demo project called gcd4 whose Source/main.swift prints some things and then uses a dispatch queue and a block to print a message after 2 seconds delay.
=========
CDispatch.dispatch_after(time, queue, {
print("Delayed!")
})
The entire project is checked in at https://github.com/sheffler/gcd4 <https://github.com/sheffler/gcd4\>
and the CDispatch module is checked in at https://github.com/sheffler/CDispatch <https://github.com/sheffler/CDispatch\>
If I try to "swift build" the project, it almost works but reports that dispatch_after is not found. It seems that this function is not defined if the "blocks" feature is not provided at compilation time.
========
Compiling Swift Module 'gcd4' (1 sources)
/home/sheffler/swift/gcd4/Sources/main.swift:42:1: error: module 'CDispatch' has no member named 'dispatch_after'
CDispatch.dispatch_after(time, queue, {
^~~~~~~~~ ~~~~~~~~~~~~~~
<unknown>:0: error: build had 1 command failures
swift-build: exit(1): ["/home/sheffler/src/swift-2.2-SNAPSHOT-2015-12-01-b-ubuntu14.04/usr/bin/swift-build-tool", "-f", "/home/sheffler/swift/gcd4/.build/debug/gcd4.o/llbuild.yaml"]
I got the demo program to work by first using "swift build" to retrieve the CDispatch module, and then manually running the compiler like this (and including the "-Xcc -fblocks" arguments)
swiftc -v -o gcd4 Sources/main.swift -I .build/debug -j8 -Onone -g -Xcc -fblocks -Xcc -F-module-map=Packages/CDispatch-1.0.0/module.modulemap -I Packages/CDispatch-1.0.0 -I /usr/local/include
The text was updated successfully, but these errors were encountered: