-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[SR-486] swiftc does not properly handle include of headers already imported from headers in other modules. #43103
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
Comments
Swift version 2.2-dev (LLVM 3ebdbb2c7e, Clang f66c5bb67b, Swift faba6e5) |
I can't think of anything that changed recently. @DougGregor? (Regardless, it's not really Swift's fault. "Headers already imported from headers in other modules" means that the header belongs in its own module. A header can't belong to two modules.) |
Comment by Mish Awadah (JIRA) CI began hitting this at the following revisions: Commit 1ea703c by nrotem Commit f182d39 by nrotem Commit c3c0f23 by lukeh Define CFBool when MACTYPES and _OS_OSTYPES_H are defined |
The previous behavior was a warning <unknown>:0: warning: ambiguous use of internal linkage declaration 'PTHREAD_MUTEX_RECURSIVE' defined in multiple modules |
Comment by Bryan Chan (JIRA) With a recent version of the master branch, I am seeing a similar issue when building a Swift package that imports a C library whose header includes pthread.h. Is it the same bug?
The module map in CLibFoo looks like this: module CLibFoo [system] {
header "/home/bryanpkc/src/ModuleBug/libfoo/foo.h"
link "foo"
export *
} The header file foo.h contains only this: #include <pthread.h>
pthread_mutex_t *getFooMutex(); |
Comment by Bryan Chan (JIRA) Apparently the issue I encountered has been discussed on the mailing list. Replacing <pthread.h> with <bits/pthreadtypes.h> works around the problem. However, it is not always possible to modify the header files of the C library one wishes to import into Swift. |
I think I've hit this long-standing issue when natively building Swift on Android now, looks to me the FreeBSD issue detailed in SR-6034 is likely the same. After drodriguez's recent pull to add more Bionic headers to the stdlib modulemap, I started getting errors about multiple declarations of fcntl: While building module 'SwiftOverlayShims':
In file included from <module-includes>:1:
/data/data/com.termux/files/home/src/swift/build/Ninja-Release/swift-android-aarch64/./lib/swift/shims/LibcOverlayShims.h:43:10: error: conflicting types for 'fcntl'
return fcntl(fd, cmd, value);
^
<module-includes>:1:10: note: in file included from <module-includes>:1:
#include "LibcOverlayShims.h"
^
/data/data/com.termux/files/home/src/swift/build/Ninja-Release/swift-android-aarch64/./lib/swift/shims/LibcOverlayShims.h:43:10: error: conflicting types for 'fcntl'
return fcntl(fd, cmd, value);
^
/data/data/com.termux/files/usr/include/bits/fcntl.h:36:5: note: previous declaration is here
int fcntl(int __fd, int __cmd, ...);
^
/data/data/com.termux/files/usr/include/bits/fcntl.h:36:5: note: previous declaration is here
int fcntl(int __fd, int __cmd, ...);
^ Note that the Bionic fcntl is declared in the nested header bits/fcntl.h, a nested declaration similar to the FreeBSD issue mentioned above, not directly in fcntl.h as in glibc. Looking into it further, the issue appears to be that the Termux environment modifies Bionic's syslog.h and ifaddrs.h to include unistd.h, which also includes bits/fcntl.h just like fcntl.h, and so runs into this nested header problem with the Swift clang setup. My best guess is that the ClangImporter in the Swift compiler doesn't keep preprocessor defines from nested headers like bits/fcntl.h, so include guards in those headers are ignored and cause havoc with modulemaps, when Swift code tries to use declarations from nested headers that might be included by multiple headers listed in the modulemap. This seems to be confirmed by this patch that worked around the problem for me: diff --git a/stdlib/public/Platform/glibc.modulemap.gyb b/stdlib/public/Platform/glibc.modulemap.gyb index 92a0948505..ad2f2c7b78 100644 --- a/stdlib/public/Platform/glibc.modulemap.gyb +++ b/stdlib/public/Platform/glibc.modulemap.gyb
@@ -248,10 +250,12 @@ module SwiftGlibc [system] { header "${GLIBC_INCLUDE_PATH}/netdb.h" export * } +% if CMAKE_SDK != "ANDROID": module ifaddrs { header "${GLIBC_INCLUDE_PATH}/ifaddrs.h" export * } +% end
module search { header "${GLIBC_INCLUDE_PATH}/search.h" export *
@@ -260,10 +264,12 @@ module SwiftGlibc [system] { header "${GLIBC_INCLUDE_PATH}/spawn.h" export * } +% if CMAKE_SDK != "ANDROID": module syslog { header "${GLIBC_INCLUDE_PATH}/syslog.h" export * } +% end
module tar { header "${GLIBC_INCLUDE_PATH}/tar.h" export * @@ -521,6 +531,14 @@ module SwiftGlibc [system] { header "${GLIBC_INCLUDE_PATH}/unistd.h" export * } + module ifaddrs { + header "${GLIBC_INCLUDE_PATH}/ifaddrs.h" + export * + } + module syslog { + header "${GLIBC_INCLUDE_PATH}/syslog.h" + export * + } module utime { header "${GLIBC_INCLUDE_PATH}/utime.h" export * All this patch does is reorder the headers in the libc modulemap so that both ifaddrs.h and syslog.h come after unistd.h, so that its include guard is defined by then and unistd.h is presumably ignored for those two headers after that. I came up with that workaround before finding this Jira issue, I just tried this workaround to directly list the nested header in the modulemap and it also seems to work: @@ -341,6 +341,14 @@ module SwiftGlibc [system] { header "${GLIBC_INCLUDE_PATH}/fcntl.h" export * } + module bits { + export * + + module fcntl { + header "${GLIBC_INCLUDE_PATH}/bits/fcntl.h" + export * + } + } module fnmatch { header "${GLIBC_INCLUDE_PATH}/fnmatch.h" export * I'm also able to reproduce this nested header problem on linux, say if I try to invoke a type from bits/types.h in LibcOverlayShims.h: diff --git a/stdlib/public/SwiftShims/LibcOverlayShims.h b/stdlib/public/SwiftShims/LibcOverlayShims.h index a4ec14402a..fbdb498ffb 100644 --- a/stdlib/public/SwiftShims/LibcOverlayShims.h +++ b/stdlib/public/SwiftShims/LibcOverlayShims.h @@ -40,7 +40,8 @@ typedef int mode_t; // File control <fcntl.h> #if !defined(_WIN32) || defined(__CYGWIN__) static inline int _swift_stdlib_fcntl(int fd, int cmd, int value) { - return fcntl(fd, cmd, value); + __uint8_t foo; + return fcntl(fd, cmd, value); } static inline int _swift_stdlib_fcntlPtr(int fd, int cmd, void* ptr) { I then get a similar error since bits/types.h is included all over the place in glibc: <module-includes>:1:10: note: in file included from <module-includes>:1: #include "LibcOverlayShims.h" ^ /home/butta/swift/build/Ninja-Release/swift-linux-x86_64/./lib/swift/shims/LibcOverlayShims.h:43:2: error: declaration of '__uint8_t' must be imported from module 'SwiftGlibc.POSIX.termios' before it is required __uint8_t foo; ^ //usr/include/bits/types.h:38:23: note: previous declaration is here typedef unsigned char __uint8_t; ^ /home/butta/swift/swift/stdlib/public/Platform/Platform.swift:14:8: error: could not build C module 'SwiftOverlayShims' import SwiftOverlayShims ^ Of course, nobody would actually directly invoke __uint8_t: this is just to demonstrate the nested header problem is there on linux too, not just Android and FreeBSD. I was unable to follow Bryan Chan's gmane link above to a swift-devel discussion about this issue, as that gmane site seems to be down, or find that thread elsewhere: maybe this problem is well-known. If it's not going to be fixed in the compiler, it should be documented prominently when using modulemaps. |
Additional Detail from JIRA
md5: cc5f2e28759eb92ea98f4446682f6e9e
Issue Description:
swiftc does not properly handle include of headers already imported from headers in other modules; this is a regression in that previously it would emit a warning and now is emitting an error
x86_64/Foundation/Foundation/NSLock.swift.o.swiftdeps -module-cache-path ../Ninja-ReleaseAssert/foundation-linux-x86_64
Foundation/NSLock.swift:147:52: error: ambiguous use of 'PTHREAD_MUTEX_RECURSIVE'
pthread_mutexattr_settype(attrs, Int32(PTHREAD_MUTEX_RECURSIVE))
^
SwiftGlibc.PTHREAD_MUTEX_RECURSIVE:1:12: note: found this candidate
public var PTHREAD_MUTEX_RECURSIVE: Int { get }
^
CoreFoundation.PTHREAD_MUTEX_RECURSIVE:1:12: note: found this candidate
public var PTHREAD_MUTEX_RECURSIVE: Int { get }
The text was updated successfully, but these errors were encountered: