diff --git a/stdlib/public/Platform/CMakeLists.txt b/stdlib/public/Platform/CMakeLists.txt index c7e7bac10925d..a7a60a063d9aa 100644 --- a/stdlib/public/Platform/CMakeLists.txt +++ b/stdlib/public/Platform/CMakeLists.txt @@ -119,6 +119,13 @@ foreach(sdk ${SWIFT_SDKS}) list(APPEND glibc_modulemap_target_list ${copy_glibc_modulemap_static}) endif() + set(glibc_header_out "${module_dir}/SwiftGlibc.h") + handle_gyb_source_single(glibc_header_target + SOURCE "SwiftGlibc.h.gyb" + OUTPUT "${glibc_header_out}" + FLAGS "-DCMAKE_SDK=${sdk}") + list(APPEND glibc_modulemap_target_list ${glibc_header_target}) + # If this SDK is a target for a non-native host, except if it's for Android # with its own native sysroot, create a native modulemap without a sysroot # prefix. This is the one we'll install instead. @@ -150,11 +157,17 @@ foreach(sdk ${SWIFT_SDKS}) swift_install_in_component(FILES "${glibc_modulemap_out}" DESTINATION "lib/swift/${arch_subdir}" COMPONENT sdk-overlay) + swift_install_in_component(FILES "${glibc_header_out}" + DESTINATION "lib/swift/${arch_subdir}" + COMPONENT sdk-overlay) if(SWIFT_BUILD_STATIC_STDLIB) swift_install_in_component(FILES "${glibc_modulemap_out}" DESTINATION "lib/swift_static/${arch_subdir}" COMPONENT sdk-overlay) + swift_install_in_component(FILES "${glibc_header_out}" + DESTINATION "lib/swift_static/${arch_subdir}" + COMPONENT sdk-overlay) endif() endforeach() endforeach() diff --git a/stdlib/public/Platform/SwiftGlibc.h.gyb b/stdlib/public/Platform/SwiftGlibc.h.gyb new file mode 100644 index 0000000000000..3391eaee29934 --- /dev/null +++ b/stdlib/public/Platform/SwiftGlibc.h.gyb @@ -0,0 +1,107 @@ +%{ +headers = [ + 'stdc-predef.h', + 'features.h', + + # C standard library + 'complex.h', + 'ctype.h', + 'errno.h', + 'fenv.h', + 'float.h', + 'inttypes.h', + 'iso646.h', + 'libutil.h', + 'limits.h', + 'locale.h', + 'math.h', + 'pty.h', + 'setjmp.h', + 'signal.h', + 'stdarg.h', + 'stdbool.h', + 'stddef.h', + 'stdint.h', + 'stdio.h', + 'stdlib.h', + 'string.h', + 'tgmath.h', + 'time.h', + 'utmp.h', + 'utmpx.h', + + # POSIX + 'aio.h', + 'arpa/inet.h', + 'bsd/ifaddrs.h', + 'bsd/pty.h', + 'cpio.h', + 'dirent.h', + 'dlfcn.h', + 'fcntl.h', + 'fmtmsg.h', + 'fnmatch.h', + 'ftw.h', + 'glob.h', + 'grp.h', + 'iconv.h', + 'ifaddrs.h', + 'langinfo.h', + 'libgen.h', + 'link.h', + 'monetary.h', + 'net/if.h', + 'netdb.h', + 'netinet/in.h', + 'netinet/tcp.h', + 'nl_types.h', + 'poll.h', + 'pthread.h', + 'pwd.h', + 'regex.h', + 'sched.h', + 'search.h', + 'semaphore.h', + 'spawn.h', + 'strings.h', + 'sys/event.h', + 'sys/file.h', + 'sys/inotify.h', + 'sys/ioctl.h', + 'sys/ipc.h', + 'sys/mman.h', + 'sys/msg.h', + 'sys/resource.h', + 'sys/select.h', + 'sys/sem.h', + 'sys/sendfile.h', + 'sys/shm.h', + 'sys/socket.h', + 'sys/stat.h', + 'sys/statvfs.h', + 'sys/time.h', + 'sys/times.h', + 'sys/types.h', + 'sys/uio.h', + 'sys/un.h', + 'sys/user.h', + 'sys/utsname.h', + 'sys/wait.h', + 'sysexits.h', + 'syslog.h', + 'tar.h', + 'termios.h', + 'ulimit.h', + 'unistd.h', + 'utime.h', + 'utmpx.h', + 'wait.h', + 'wordexp.h', +] +}% + +% for header in headers: +#if __has_include(<${header}>) +#include <${header}> +#endif +% end diff --git a/stdlib/public/Platform/glibc.modulemap.gyb b/stdlib/public/Platform/glibc.modulemap.gyb index 9a88a108c74c3..455dd111e2ce3 100644 --- a/stdlib/public/Platform/glibc.modulemap.gyb +++ b/stdlib/public/Platform/glibc.modulemap.gyb @@ -19,6 +19,9 @@ /// It's not named just Glibc so that it doesn't conflict in the event of a /// future official glibc modulemap. module SwiftGlibc [system] { +% if CMAKE_SDK == "LINUX": + link "m" +% end % if CMAKE_SDK in ["LINUX", "FREEBSD", "CYGWIN"]: link "pthread" // FIXME: util contains rarely used functions and not usually needed. Unfortunately @@ -36,506 +39,8 @@ module SwiftGlibc [system] { link "execinfo" % end - // C standard library - module C { -% if CMAKE_SDK in ["LINUX", "CYGWIN"]: - module features { -% if CMAKE_SDK == "LINUX": - header "${GLIBC_INCLUDE_PATH}/stdc-predef.h" -% end - header "${GLIBC_INCLUDE_PATH}/features.h" - export * - } -% end -% if CMAKE_SDK in ["LINUX", "FREEBSD", "CYGWIN", "HAIKU"]: - module complex { - header "${GLIBC_INCLUDE_PATH}/complex.h" - export * - } -% end -% if CMAKE_SDK in ["LINUX", "CYGWIN"]: - module pty { - header "${GLIBC_INCLUDE_PATH}/pty.h" - export * - } - module utmp { - header "${GLIBC_INCLUDE_PATH}/utmp.h" - export * - } -% end -% if CMAKE_SDK == "FREEBSD": - module pty { - header "${GLIBC_INCLUDE_PATH}/libutil.h" - export * - } - module utmp { - header "${GLIBC_INCLUDE_PATH}/utmpx.h" - export * - } -% end -% if CMAKE_SDK == "HAIKU": - module pty { - header "${GLIBC_INCLUDE_PATH}/../bsd/pty.h" - export * - } -% end - - module ctype { - header "${GLIBC_INCLUDE_PATH}/ctype.h" - export * - } - module errno { - header "${GLIBC_INCLUDE_PATH}/errno.h" - export * - } - - module fenv { - header "${GLIBC_INCLUDE_PATH}/fenv.h" - export * - } - - // note: supplied by compiler - // module float { - // header "${GLIBC_INCLUDE_PATH}/float.h" - // export * - // } - - module inttypes { - header "${GLIBC_INCLUDE_PATH}/inttypes.h" - export * - } - - // note: potentially supplied by compiler - // module iso646 { - // header "${GLIBC_INCLUDE_PATH}/iso646.h" - // export * - // } - // module limits { - // header "${GLIBC_INCLUDE_PATH}/limits.h" - // export * - // } - - module locale { - header "${GLIBC_INCLUDE_PATH}/locale.h" - export * - } - module math { -% if CMAKE_SDK == "LINUX": - link "m" -% end - header "${GLIBC_INCLUDE_PATH}/math.h" - export * - } -% if CMAKE_SDK != "WASI": - module setjmp { - header "${GLIBC_INCLUDE_PATH}/setjmp.h" - export * - } -% end - module signal { - header "${GLIBC_INCLUDE_PATH}/signal.h" - export * - } - - // note: supplied by the compiler - // module stdarg { - // header "${GLIBC_INCLUDE_PATH}/stdarg.h" - // export * - // } - // module stdbool { - // header "${GLIBC_INCLUDE_PATH}/stdbool.h" - // export * - // } - // module stddef { - // header "${GLIBC_INCLUDE_PATH}/stddef.h" - // export * - // } - // module stdint { - // header "${GLIBC_INCLUDE_PATH}/stdint.h" - // export * - // } - - module stdio { - header "${GLIBC_INCLUDE_PATH}/stdio.h" - export * - } - module stdlib { - header "${GLIBC_INCLUDE_PATH}/stdlib.h" - export * - export stddef - } - module string { - header "${GLIBC_INCLUDE_PATH}/string.h" - export * - } - - // note: supplied by the compiler - // explicit module tgmath { - // header "${GLIBC_INCLUDE_PATH}/tgmath.h" - // export * - // } - - module time { - header "${GLIBC_INCLUDE_PATH}/time.h" - export * - } - } - - // POSIX - module POSIX { -% if CMAKE_SDK in ["LINUX", "CYGWIN"]: - module wait { - header "${GLIBC_INCLUDE_PATH}/wait.h" - export * - } -% end - -% if CMAKE_SDK in ["LINUX", "FREEBSD"]: - module aio { - header "${GLIBC_INCLUDE_PATH}/aio.h" - export * - } - module cpio { - header "${GLIBC_INCLUDE_PATH}/cpio.h" - export * - } - module fmtmsg { - header "${GLIBC_INCLUDE_PATH}/fmtmsg.h" - export * - } - module nl_types { - header "${GLIBC_INCLUDE_PATH}/nl_types.h" - export * - } - module ulimit { - header "${GLIBC_INCLUDE_PATH}/ulimit.h" - export * - } -% end - -% if CMAKE_SDK in ["LINUX", "FREEBSD", "CYGWIN"]: - module ftw { - header "${GLIBC_INCLUDE_PATH}/ftw.h" - export * - } - module glob { - header "${GLIBC_INCLUDE_PATH}/glob.h" - export * - } - module iconv { - header "${GLIBC_INCLUDE_PATH}/iconv.h" - export * - } - module langinfo { - header "${GLIBC_INCLUDE_PATH}/langinfo.h" - export * - } - module monetary { - header "${GLIBC_INCLUDE_PATH}/monetary.h" - export * - } - module netdb { - header "${GLIBC_INCLUDE_PATH}/netdb.h" - export * - } - module ifaddrs { - header "${GLIBC_INCLUDE_PATH}/ifaddrs.h" - export * - } - module search { - header "${GLIBC_INCLUDE_PATH}/search.h" - export * - } - module spawn { - header "${GLIBC_INCLUDE_PATH}/spawn.h" - export * - } - module syslog { - header "${GLIBC_INCLUDE_PATH}/syslog.h" - export * - } - module tar { - header "${GLIBC_INCLUDE_PATH}/tar.h" - export * - } - module utmpx { - header "${GLIBC_INCLUDE_PATH}/utmpx.h" - export * - } - module wordexp { - header "${GLIBC_INCLUDE_PATH}/wordexp.h" - export * - } -% end - -% if CMAKE_SDK == "HAIKU": - module ftw { - header "${GLIBC_INCLUDE_PATH}/ftw.h" - export * - } - module glob { - header "${GLIBC_INCLUDE_PATH}/glob.h" - export * - } - module iconv { - header "${GLIBC_INCLUDE_PATH}/../iconv.h" - export * - } - module langinfo { - header "${GLIBC_INCLUDE_PATH}/langinfo.h" - export * - } - module monetary { - header "${GLIBC_INCLUDE_PATH}/monetary.h" - export * - } - module netdb { - header "${GLIBC_INCLUDE_PATH}/netdb.h" - export * - } - module ifaddrs { - header "${GLIBC_INCLUDE_PATH}/../bsd/ifaddrs.h" - export * - } - module search { - header "${GLIBC_INCLUDE_PATH}/search.h" - export * - } - module syslog { - header "${GLIBC_INCLUDE_PATH}/syslog.h" - export * - } - module tar { - header "${GLIBC_INCLUDE_PATH}/tar.h" - export * - } -% end - module arpa { - module inet { - header "${GLIBC_INCLUDE_PATH}/arpa/inet.h" - export * - } - export * - } - module dirent { - header "${GLIBC_INCLUDE_PATH}/dirent.h" - export * - } -% if CMAKE_SDK != "WASI": - module dl { - header "${GLIBC_INCLUDE_PATH}/link.h" - export * - } - module dlfcn { - header "${GLIBC_INCLUDE_PATH}/dlfcn.h" - export * - } -% end - module fcntl { - header "${GLIBC_INCLUDE_PATH}/fcntl.h" - export * - } - module fnmatch { - header "${GLIBC_INCLUDE_PATH}/fnmatch.h" - export * - } -% if CMAKE_SDK != "WASI": - module grp { - header "${GLIBC_INCLUDE_PATH}/grp.h" - export * - } -% end - module ioctl { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/ioctl.h" - export * - } - module libgen { - header "${GLIBC_INCLUDE_PATH}/libgen.h" - export * - } -% if CMAKE_SDK != "WASI": - module net { - module if { - header "${GLIBC_INCLUDE_PATH}/net/if.h" - export * - } - } -% end - module netinet { - module in { - header "${GLIBC_INCLUDE_PATH}/netinet/in.h" - export * - - exclude header "${GLIBC_INCLUDE_PATH}/netinet6/in6.h" - } - module tcp { - header "${GLIBC_INCLUDE_PATH}/netinet/tcp.h" - export * - } - } - module poll { - header "${GLIBC_INCLUDE_PATH}/poll.h" - export * - } -% if CMAKE_SDK != "WASI": - module pthread { - header "${GLIBC_INCLUDE_PATH}/pthread.h" - export * - } -% end - module pwd { - header "${GLIBC_INCLUDE_PATH}/pwd.h" - export * - } - module regex { - header "${GLIBC_INCLUDE_PATH}/regex.h" - export * - } - module sched { - header "${GLIBC_INCLUDE_PATH}/sched.h" - export * - } - module semaphore { - header "${GLIBC_INCLUDE_PATH}/semaphore.h" - export * - } - module strings { - header "${GLIBC_INCLUDE_PATH}/strings.h" - export * - } - - module sys { - export * - -% if CMAKE_SDK in ["LINUX", "FREEBSD", "CYGWIN", "HAIKU"]: - module file { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/file.h" - export * - } - module sem { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/sem.h" - export * - } -% if CMAKE_SDK != "HAIKU": - module shm { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/shm.h" - export * - } - module inotify { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/inotify.h" - export * - } -% end - module statvfs { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/statvfs.h" - export * - } -% end - -% if CMAKE_SDK != "WASI": - module ipc { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/ipc.h" - export * - } -% end - module mman { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/mman.h" - export * - } -% if CMAKE_SDK != "WASI": - module msg { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/msg.h" - export * - } -% end - module resource { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/resource.h" - export * - } - module select { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/select.h" - export * - } -% if CMAKE_SDK != "FREEBSD" and CMAKE_SDK != "HAIKU" and CMAKE_SDK != "WASI": - module sendfile { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/sendfile.h" - export * - } -% end - module socket { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/socket.h" - export * - } - module stat { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/stat.h" - export * - } - module time { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/time.h" - export * - } - module times { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/times.h" - export * - } - module types { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/types.h" - export * - } -% if CMAKE_SDK in ["FREEBSD"]: - module event { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/event.h" - export * - } -% end - module uio { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/uio.h" - export * - } - module un { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/un.h" - export * - } -% if CMAKE_SDK in ["LINUX"]: - module user { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/user.h" - export * - } -% end - module utsname { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/utsname.h" - export * - } -% if CMAKE_SDK != "WASI": - module wait { - header "${GLIBC_ARCH_INCLUDE_PATH}/sys/wait.h" - export * - } - } -% end -% if CMAKE_SDK in ["LINUX", "FREEBSD"]: - module sysexits { - header "${GLIBC_INCLUDE_PATH}/sysexits.h" - export * - } -% end -% if CMAKE_SDK != "WASI": - module termios { - header "${GLIBC_INCLUDE_PATH}/termios.h" - export * - } -% end - module unistd { - header "${GLIBC_INCLUDE_PATH}/unistd.h" - export * - } -% if CMAKE_SDK != "WASI": - module utime { - header "${GLIBC_INCLUDE_PATH}/utime.h" - export * - } - } -% end + header "SwiftGlibc.h" + export * } % if CMAKE_SDK != "WASI": diff --git a/test/Interop/C/libc/Inputs/include-signal.h b/test/Interop/C/libc/Inputs/include-signal.h new file mode 100644 index 0000000000000..019db1a7f5097 --- /dev/null +++ b/test/Interop/C/libc/Inputs/include-signal.h @@ -0,0 +1,8 @@ +#ifndef TEST_INTEROP_C_LIBC_INPUTS_INCLUDE_SIGNAL_H +#define TEST_INTEROP_C_LIBC_INPUTS_INCLUDE_SIGNAL_H + +#include + +pid_t returnPidT(); + +#endif // TEST_INTEROP_C_LIBC_INPUTS_INCLUDE_SIGNAL_H \ No newline at end of file diff --git a/test/Interop/C/libc/Inputs/module.modulemap b/test/Interop/C/libc/Inputs/module.modulemap new file mode 100644 index 0000000000000..566cb2144e560 --- /dev/null +++ b/test/Interop/C/libc/Inputs/module.modulemap @@ -0,0 +1,3 @@ +module IncludeSignal { + header "include-signal.h" +} diff --git a/test/Interop/C/libc/include-signal.swift b/test/Interop/C/libc/include-signal.swift new file mode 100644 index 0000000000000..3b420364f3ce8 --- /dev/null +++ b/test/Interop/C/libc/include-signal.swift @@ -0,0 +1,33 @@ +// RUN: %target-typecheck-verify-swift -I %S/Inputs + +// Some types such as pid_t that glibc defines are defined using the following +// construct: +// +// #ifndef __pid_t_defined +// typedef __pid_t pid_t; +// #define __pid_t_defined +// #endif +// +// glibc defines pid_t in this way in multiple header files, as required by +// POSIX (e.g. signal.h, unistd.h, and sys/types.h). A number of other types +// use the same construct (e.g. ssize_t, intptr_t, uid_t, gid_t). +// +// Because Swift does not set the -fmodules-local-submodule-visibility flag, +// the __pid_t_defined macro can leak from the first submodule that defines it +// into all submodules that follow. +// +// As a consequence, a C header file may fail to compile when imported into +// Swift, even though it compiles cleanly outside Swift with the same system +// headers. +// +// This is a regression test for a bug that was once present in SwiftGlibc +// module layout. Originally SwiftGlibc defined one submodule per header, and +// types such as pid_t were defined by the first module that encountered the +// ifndef construct. +// +// See https://forums.swift.org/t/problems-with-swiftglibc-and-proposed-fix/37594 +// for further details. + +// REQUIRES: OS=linux-gnu + +import IncludeSignal \ No newline at end of file diff --git a/test/Interop/Cxx/libc/include-glibc.swift b/test/Interop/Cxx/libc/include-glibc.swift new file mode 100644 index 0000000000000..116dc88895783 --- /dev/null +++ b/test/Interop/Cxx/libc/include-glibc.swift @@ -0,0 +1,15 @@ +// RUN: %target-run-simple-swift(-Xfrontend -enable-cxx-interop) + +// REQUIRES: executable_test +// REQUIRES: OS=linux-gnu + +import Glibc +import StdlibUnittest + +var GlibcTests = TestSuite("GlibcTests") + +GlibcTests.test("abs") { + expectEqual(42, abs(-42)) +} + +runAllTests()