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-6772] Swift packages do not correctly respect _GNU_SOURCE declaration when it is present in imported modules. #49321
Comments
The whole point of modules is that they do not affect how other headers are interpreted. That would defeat the purpose. But SR-360 says we should consider just turning this on all the time. |
Ok, I understand that argument. I have some questions about it. 1. Perhaps this is just me not understanding clang modules, but why does passing |
You can read more about modules on the Clang website: http://clang.llvm.org/docs/Modules.html. The entire purpose, independent of Swift, is to make it so that headers won't step on each other. It's okay to do it from the command line because then things are consistent across the entire compilation. |
So my current workaround involves defining a C module as a shim. It has a header file: #include <sys/socket.h>
typedef struct {
struct msghdr msg_hdr;
unsigned int msg_len;
} CShim_mmsghdr;
int CShim_sendmmsg(int sockfd, CShim_mmsghdr *msgvec, unsigned int vlen, int flags);
int CShim_recvmmsg(int sockfd, CShim_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout); And one C file: #define _GNU_SOURCE
#include <c_shim.h>
int CShim_sendmmsg(int sockfd, CShim_mmsghdr *msgvec, unsigned int vlen, int flags) {
return sendmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags);
}
int CShim_recvmmsg(int sockfd, CShim_mmsghdr *msgvec, unsigned int vlen, int flags, struct timespec *timeout) {
return recvmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags, timeout);
} The Swift code imports this module and sees the regular This workaround works just fine (except for the UB I'm invoking with the pointer cast). Is this considered an appropriate workaround for this behaviour? |
Yep, that's a totally fine workaround. Sorry it's not better. |
Attachment: Download
Environment
Linux 4f8db028d077 4.9.60-linuxkit-aufs #1 SMP Mon Nov 6 16:00:12 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
Swift version 4.0.2 (swift-4.0.2-RELEASE)
Target: x86_64-unknown-linux-gnu
Additional Detail from JIRA
md5: c23c4bef4a8c3b0104ebda413e1a3594
Issue Description:
I'm attempting to use some symbols from glibc that are normally hidden behind a _GNU_SOURCE macro definition. To do this, I've written a small SwiftPM module that provides a C header file that includes
sys/socket.h
after defining _GNU_SOURCE, to make the symbols available from that module to Swift.Unfortunately, it seems like something in the Swift build toolchain, possibly the clang importer, is getting this wrong. To demonstrate the problem I've attached a small SwiftPM repro package that defines two modules: CMmesg, the C shim, and MMesg, a Swift module that attempts to use the symbols.
Example breakdown
For this example I'm using the
mmsghdr
structure defined insocket.h
on Linux.The project ultimately consists of three files. Firstly, a simple header file:
The main goal of this header file is to bring in the types from
sys/socket.h
, but we also forward-declare the two functions in the following C file. The C file exists to prove that, when compiling just the C code, SwiftPM correctly applies_GNU_SOURCE
. It looks like this:This demonstrates that the C code is capable of seeing the structure definition for
struct mmsghdr
, as it uses it as a concrete type and knows its size.Then we have a simple bit of Swift code:
This code attempts to create a
struct mmsghdr
and print it.Error
The compile fails with:
Exploration
The initial problem is that the Swift compiler does not seem to see the structure definitions behind
_GNU_SOURCE
. You can play about with the Swift program to demonstrate this in a few ways. For example, if you changemain.swift
to instead callallocateMMsg
, you'll find that this works, but Swift returns anOpaquePointer
, indicating the compiler does not know the size of the type. If you try to callreturnMMsg
the Swift compiler will complain that it doesn't know what this function is, indicating that rather than barf on the use of the concrete type it's simply decided to elide the symbol definition altogether.If you change from calling
swift run
toswift run -Xcc -D_GNU_SOURCE
, the compile will start succeeding and it'll see the type. If you useswift run -Xswiftc -D_GNU_SOURCE
the compile will not succeed.Ramifications
In order to using anything from glibc that is hidden behind
_GNU_SOURCE
there are only two options. Either have all users pass-Xcc -D_GNU_SOURCE
when building the tool, or use a C shim module that never exposes the missing types concretely, either by providing its own types or by forward-declaring them.This can be done, but it's a substantial annoyance.
More generally, this shows a lack of sane handling of C header files. In this case the ramifications are minor, but with this code it's possible that a C module and its corresponding Swift module may end up disagreeing on the size or memory layout of structures, potentially violating the memory safety that Swift is supposed to provide.
The text was updated successfully, but these errors were encountered: