Skip to content

Commit ba061fa

Browse files
[wasm][build] Add WASILibc module and its build support
[wasi-libc](https://github.com/WebAssembly/wasi-libc) is a libc implementation widely used in WASI toolchains. This patch adds a new Swift and C module for it to import and use it in Swift code. This module is intentionally separate from the existing `Glibc` module because wasi-libc is actually based on musl libc.
1 parent 4e2f3b1 commit ba061fa

File tree

4 files changed

+343
-13
lines changed

4 files changed

+343
-13
lines changed

stdlib/public/Platform/CMakeLists.txt

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,23 @@ add_swift_target_library(swiftGlibc ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_O
9898
INSTALL_IN_COMPONENT sdk-overlay
9999
DEPENDS glibc_modulemap)
100100

101+
add_swift_target_library(swiftWASILibc ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
102+
${swift_platform_sources}
103+
POSIXError.swift
104+
105+
GYB_SOURCES
106+
${swift_platform_gyb_sources}
107+
WASILibc.swift.gyb
108+
109+
SWIFT_COMPILE_FLAGS
110+
${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}
111+
${SWIFT_STANDARD_LIBRARY_SWIFT_FLAGS}
112+
${swift_platform_compile_flags}
113+
LINK_FLAGS "${SWIFT_RUNTIME_SWIFT_LINK_FLAGS}"
114+
TARGET_SDKS WASI
115+
INSTALL_IN_COMPONENT sdk-overlay
116+
DEPENDS glibc_modulemap)
117+
101118
add_swift_target_library(swiftCRT ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVERLAY
102119
ucrt.swift
103120
${swift_platform_sources}
@@ -117,23 +134,31 @@ add_swift_target_library(swiftCRT ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES} IS_SDK_OVE
117134

118135
set(glibc_modulemap_target_list)
119136
foreach(sdk ${SWIFT_SDKS})
120-
if(NOT "${sdk}" STREQUAL "LINUX" AND
121-
NOT "${sdk}" STREQUAL "FREEBSD" AND
122-
NOT "${sdk}" STREQUAL "OPENBSD" AND
123-
NOT "${sdk}" STREQUAL "ANDROID" AND
124-
NOT "${sdk}" STREQUAL "CYGWIN" AND
125-
NOT "${sdk}" STREQUAL "HAIKU")
137+
if("${sdk}" STREQUAL "LINUX" OR
138+
"${sdk}" STREQUAL "FREEBSD" OR
139+
"${sdk}" STREQUAL "OPENBSD" OR
140+
"${sdk}" STREQUAL "ANDROID" OR
141+
"${sdk}" STREQUAL "CYGWIN" OR
142+
"${sdk}" STREQUAL "HAIKU")
143+
set(glibc_modulemap_source "glibc.modulemap.gyb")
144+
set(glibc_header_source "SwiftGlibc.h.gyb")
145+
elseif("${sdk}" STREQUAL "WASI")
146+
set(glibc_modulemap_source "wasi-libc.modulemap.gyb")
147+
set(glibc_header_source "SwiftWASILibc.h.gyb")
148+
else()
126149
continue()
127150
endif()
128151

152+
string(REGEX REPLACE "\\.gyb$" "" glibc_modulemap_outname "${glibc_modulemap_source}")
153+
string(REGEX REPLACE "\\.gyb$" "" glibc_header_outname "${glibc_header_source}")
154+
129155
foreach(arch ${SWIFT_SDK_${sdk}_ARCHITECTURES})
130156
set(arch_subdir "${SWIFT_SDK_${sdk}_LIB_SUBDIR}/${arch}")
131157
set(module_dir "${SWIFTLIB_DIR}/${arch_subdir}")
132158
set(module_dir_static "${SWIFTSTATICLIB_DIR}/${arch_subdir}")
133159

134-
set(glibc_modulemap_source "glibc.modulemap.gyb")
135-
set(glibc_modulemap_out "${module_dir}/glibc.modulemap")
136-
set(glibc_modulemap_out_static "${module_dir_static}/glibc.modulemap")
160+
set(glibc_modulemap_out "${module_dir}/${glibc_modulemap_outname}")
161+
set(glibc_modulemap_out_static "${module_dir_static}/${glibc_modulemap_outname}")
137162

138163
# Configure the module map based on the target. Each platform needs to
139164
# reference different headers, based on what's available in their glibc.
@@ -147,10 +172,10 @@ foreach(sdk ${SWIFT_SDKS})
147172

148173
list(APPEND glibc_modulemap_target_list ${glibc_modulemap_target})
149174

150-
set(glibc_header_out "${module_dir}/SwiftGlibc.h")
151-
set(glibc_header_out_static "${module_dir_static}/SwiftGlibc.h")
175+
set(glibc_header_out "${module_dir}/${glibc_header_outname}")
176+
set(glibc_header_out_static "${module_dir_static}/${glibc_header_outname}")
152177
handle_gyb_source_single(glibc_header_target
153-
SOURCE "SwiftGlibc.h.gyb"
178+
SOURCE "${glibc_header_source}"
154179
OUTPUT "${glibc_header_out}"
155180
FLAGS "-DCMAKE_SDK=${sdk}")
156181
list(APPEND glibc_modulemap_target_list ${glibc_header_target})
@@ -181,7 +206,7 @@ foreach(sdk ${SWIFT_SDKS})
181206
# prefix. This is the one we'll install instead.
182207
if(NOT "${SWIFT_SDK_${SWIFT_HOST_VARIANT_SDK}_ARCH_${arch}_PATH}" STREQUAL "/" AND
183208
NOT (${sdk} STREQUAL ANDROID AND NOT "${SWIFT_ANDROID_NATIVE_SYSROOT}" STREQUAL ""))
184-
set(glibc_sysroot_relative_modulemap_out "${module_dir}/sysroot-relative-modulemaps/glibc.modulemap")
209+
set(glibc_sysroot_relative_modulemap_out "${module_dir}/sysroot-relative-modulemaps/${glibc_modulemap_outname}")
185210

186211
handle_gyb_source_single(glibc_modulemap_native_target
187212
SOURCE "${glibc_modulemap_source}"
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
%{
2+
headers = [
3+
'stdc-predef.h',
4+
'features.h',
5+
6+
# C standard library
7+
'complex.h',
8+
'ctype.h',
9+
'errno.h',
10+
'fenv.h',
11+
'float.h',
12+
'inttypes.h',
13+
'iso646.h',
14+
'libutil.h',
15+
'limits.h',
16+
'locale.h',
17+
'math.h',
18+
'pty.h',
19+
# setjmp/longjmp is not available
20+
# 'setjmp.h',
21+
'signal.h',
22+
'stdarg.h',
23+
'stdbool.h',
24+
'stddef.h',
25+
'stdint.h',
26+
'stdio.h',
27+
'stdlib.h',
28+
'string.h',
29+
'tgmath.h',
30+
'time.h',
31+
'util.h',
32+
'utmp.h',
33+
34+
# POSIX
35+
'aio.h',
36+
'arpa/inet.h',
37+
'bsd/ifaddrs.h',
38+
'bsd/pty.h',
39+
'cpio.h',
40+
'dirent.h',
41+
'dlfcn.h',
42+
'fcntl.h',
43+
'fmtmsg.h',
44+
'fnmatch.h',
45+
'ftw.h',
46+
'glob.h',
47+
'grp.h',
48+
'iconv.h',
49+
'ifaddrs.h',
50+
'langinfo.h',
51+
'libgen.h',
52+
'link.h',
53+
'monetary.h',
54+
'net/if.h',
55+
'netdb.h',
56+
'netinet/in.h',
57+
'netinet/tcp.h',
58+
'nl_types.h',
59+
'poll.h',
60+
'pthread.h',
61+
'pwd.h',
62+
'regex.h',
63+
'sched.h',
64+
'search.h',
65+
'semaphore.h',
66+
'spawn.h',
67+
'strings.h',
68+
'sys/event.h',
69+
'sys/file.h',
70+
'sys/inotify.h',
71+
'sys/ioctl.h',
72+
'sys/ipc.h',
73+
'sys/mman.h',
74+
'sys/mount.h',
75+
'sys/msg.h',
76+
'sys/resource.h',
77+
'sys/select.h',
78+
'sys/sem.h',
79+
'sys/sendfile.h',
80+
'sys/shm.h',
81+
'sys/socket.h',
82+
'sys/stat.h',
83+
'sys/statvfs.h',
84+
'sys/time.h',
85+
'sys/times.h',
86+
'sys/types.h',
87+
'sys/uio.h',
88+
'sys/un.h',
89+
'sys/user.h',
90+
'sys/utsname.h',
91+
'sys/wait.h',
92+
'sysexits.h',
93+
'syslog.h',
94+
'tar.h',
95+
'termios.h',
96+
'ulimit.h',
97+
'unistd.h',
98+
'utime.h',
99+
'utmpx.h',
100+
'wait.h',
101+
'wordexp.h',
102+
103+
# WASI specific
104+
'wasi/api.h',
105+
]
106+
}%
107+
108+
// FIXME?(katei):
109+
// Those emulations are now enabled by default to have compatibility
110+
// with other platforms as much as possible without any extra modification.
111+
// But we should consider moving them into their own submodules.
112+
#ifndef _WASI_EMULATED_MMAN
113+
# define _WASI_EMULATED_MMAN
114+
#endif
115+
#ifndef _WASI_EMULATED_SIGNAL
116+
# define _WASI_EMULATED_SIGNAL
117+
#endif
118+
#ifndef _WASI_EMULATED_PROCESS_CLOCKS
119+
# define _WASI_EMULATED_PROCESS_CLOCKS
120+
#endif
121+
122+
% for header in headers:
123+
#if __has_include(<${header}>)
124+
#include <${header}>
125+
#endif
126+
% end
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
@_exported import SwiftWASILibc // Clang module
14+
15+
// Constants defined by <math.h>
16+
@available(swift, deprecated: 3.0, message: "Please use 'Double.pi' or '.pi' to get the value of correct type and avoid casting.")
17+
public let M_PI = Double.pi
18+
19+
@available(swift, deprecated: 3.0, message: "Please use 'Double.pi / 2' or '.pi / 2' to get the value of correct type and avoid casting.")
20+
public let M_PI_2 = Double.pi / 2
21+
22+
@available(swift, deprecated: 3.0, message: "Please use 'Double.pi / 4' or '.pi / 4' to get the value of correct type and avoid casting.")
23+
public let M_PI_4 = Double.pi / 4
24+
25+
@available(swift, deprecated: 3.0, message: "Please use '2.squareRoot()'.")
26+
public let M_SQRT2 = 2.squareRoot()
27+
28+
@available(swift, deprecated: 3.0, message: "Please use '0.5.squareRoot()'.")
29+
public let M_SQRT1_2 = 0.5.squareRoot()
30+
31+
// Constants defined by <float.h>
32+
@available(swift, deprecated: 3.0, message: "Please use 'T.radix' to get the radix of a FloatingPoint type 'T'.")
33+
public let FLT_RADIX = Double.radix
34+
35+
%for type, prefix in [('Float', 'FLT'), ('Double', 'DBL')]:
36+
// Where does the 1 come from? C counts the usually-implicit leading
37+
// significand bit, but Swift does not. Neither is really right or wrong.
38+
@available(swift, deprecated: 3.0, message: "Please use '${type}.significandBitCount + 1'.")
39+
public let ${prefix}_MANT_DIG = ${type}.significandBitCount + 1
40+
41+
// Where does the 1 come from? C models floating-point numbers as having a
42+
// significand in [0.5, 1), but Swift (following IEEE 754) considers the
43+
// significand to be in [1, 2). This rationale applies to ${prefix}_MIN_EXP
44+
// as well.
45+
@available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude.exponent + 1'.")
46+
public let ${prefix}_MAX_EXP = ${type}.greatestFiniteMagnitude.exponent + 1
47+
48+
@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude.exponent + 1'.")
49+
public let ${prefix}_MIN_EXP = ${type}.leastNormalMagnitude.exponent + 1
50+
51+
@available(swift, deprecated: 3.0, message: "Please use '${type}.greatestFiniteMagnitude' or '.greatestFiniteMagnitude'.")
52+
public let ${prefix}_MAX = ${type}.greatestFiniteMagnitude
53+
54+
@available(swift, deprecated: 3.0, message: "Please use '${type}.ulpOfOne' or '.ulpOfOne'.")
55+
public let ${prefix}_EPSILON = ${type}.ulpOfOne
56+
57+
@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNormalMagnitude' or '.leastNormalMagnitude'.")
58+
public let ${prefix}_MIN = ${type}.leastNormalMagnitude
59+
60+
@available(swift, deprecated: 3.0, message: "Please use '${type}.leastNonzeroMagnitude' or '.leastNonzeroMagnitude'.")
61+
public let ${prefix}_TRUE_MIN = ${type}.leastNonzeroMagnitude
62+
63+
%end
64+
65+
public let MAP_FAILED: UnsafeMutableRawPointer! = UnsafeMutableRawPointer(bitPattern: -1)
66+
67+
// TODO: wasi-libc's error.h defines these macros as function-like macros, which
68+
// Swift can't import for now.
69+
%{
70+
posix_error_codes = [
71+
"E2BIG",
72+
"EACCES",
73+
"EADDRINUSE",
74+
"EADDRNOTAVAIL",
75+
"EAFNOSUPPORT",
76+
"EAGAIN",
77+
"EALREADY",
78+
"EBADF",
79+
"EBADMSG",
80+
"EBUSY",
81+
"ECANCELED",
82+
"ECHILD",
83+
"ECONNABORTED",
84+
"ECONNREFUSED",
85+
"ECONNRESET",
86+
"EDEADLK",
87+
"EDESTADDRREQ",
88+
"EDOM",
89+
"EDQUOT",
90+
"EEXIST",
91+
"EFAULT",
92+
"EFBIG",
93+
"EHOSTUNREACH",
94+
"EIDRM",
95+
"EILSEQ",
96+
"EINPROGRESS",
97+
"EINTR",
98+
"EINVAL",
99+
"EIO",
100+
"EISCONN",
101+
"EISDIR",
102+
"ELOOP",
103+
"EMFILE",
104+
"EMLINK",
105+
"EMSGSIZE",
106+
"EMULTIHOP",
107+
"ENAMETOOLONG",
108+
"ENETDOWN",
109+
"ENETRESET",
110+
"ENETUNREACH",
111+
"ENFILE",
112+
"ENOBUFS",
113+
"ENODEV",
114+
"ENOENT",
115+
"ENOEXEC",
116+
"ENOLCK",
117+
"ENOLINK",
118+
"ENOMEM",
119+
"ENOMSG",
120+
"ENOPROTOOPT",
121+
"ENOSPC",
122+
"ENOSYS",
123+
"ENOTCONN",
124+
"ENOTDIR",
125+
"ENOTEMPTY",
126+
"ENOTRECOVERABLE",
127+
"ENOTSOCK",
128+
"ENOTSUP",
129+
"ENOTTY",
130+
"ENXIO",
131+
"EOVERFLOW",
132+
"EOWNERDEAD",
133+
"EPERM",
134+
"EPIPE",
135+
"EPROTO",
136+
"EPROTONOSUPPORT",
137+
"EPROTOTYPE",
138+
"ERANGE",
139+
"EROFS",
140+
"ESPIPE",
141+
"ESRCH",
142+
"ESTALE",
143+
"ETIMEDOUT",
144+
"ETXTBSY",
145+
"EXDEV",
146+
"ENOTCAPABLE",
147+
]
148+
}%
149+
150+
%for ecode in posix_error_codes:
151+
152+
@available(*, deprecated, message: "Please use 'POSIXErrorCode.${ecode}'.")
153+
public let ${ecode} = POSIXErrorCode.${ecode}.rawValue
154+
155+
%end
156+
157+
// TODO: wasi-libc's _seek.h defines these macros as function-like macros, which
158+
// Swift can't import for now.
159+
public let SEEK_SET: Int32 = 0
160+
public let SEEK_CUR: Int32 = 1
161+
public let SEEK_END: Int32 = 2
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//===--- wasi-libc.modulemap.gyb ------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
module SwiftWASILibc [system] {
14+
// C standard library
15+
header "SwiftWASILibc.h"
16+
17+
export *
18+
}

0 commit comments

Comments
 (0)