Skip to content

Commit 1e5f69b

Browse files
Merge pull request #69101 from kateinoigakukun/yt/wasm-stdlib-product-pr
[wasm][build] Build stdlib and test IRGen for WebAssembly
2 parents 10fd9ff + 977b74a commit 1e5f69b

File tree

11 files changed

+401
-37
lines changed

11 files changed

+401
-37
lines changed

stdlib/public/Platform/wasi-libc.modulemap

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,12 @@ module SwiftWASILibc [system] {
1919
header "ctype.h"
2020
header "errno.h"
2121
header "fenv.h"
22-
header "float.h"
2322
header "inttypes.h"
24-
header "iso646.h"
25-
header "limits.h"
2623
header "locale.h"
2724
header "math.h"
28-
header "stdarg.h"
29-
header "stdbool.h"
30-
header "stddef.h"
31-
header "stdint.h"
3225
header "stdio.h"
3326
header "stdlib.h"
3427
header "string.h"
35-
header "tgmath.h"
3628
header "time.h"
3729

3830
// POSIX

test/IRGen/async_dynamic_replacement.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %target-swift-frontend %s -emit-ir -disable-availability-checking -disable-objc-interop | %FileCheck %s
22

33
// REQUIRES: concurrency
4+
// LLVM does not support swifttailcc for WebAssembly target for now
5+
// See https://github.com/apple/swift/issues/69333
6+
// UNSUPPORTED: CPU=wasm32
47

58
public dynamic func number() async -> Int {
69
return 100

test/IRGen/section_wasm.swift

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
// ASM-NOT: .section{{.*}}__TEXT,__mysection
88
// ASM: .section ".text.$s7section3fooyyF"
99
// ASM: $s7section3fooyyF:
10+
// ASM: .section ".text.$s7section8MyStructV3fooyyF","",@
11+
// ASM: $s7section8MyStructV3fooyyF:
1012

1113
// Wasm places one-time init token on .bss section before each "__TEXT,__mysection"
1214
// so need to put .section directives for each data to switch sections.
@@ -29,33 +31,15 @@
2931
// .size $s7section2g0Sivp, 4
3032
// ```
3133

32-
//
33-
// ASM: .section ".bss.$s7section2g0_Wz"
34-
// ASM: $s7section2g0_Wz:
35-
// ASM: .section "__TEXT,__mysection"
34+
// ASM: .section "__DATA,__mysection"
3635
// ASM: $s7section2g0Sivp:
37-
38-
// ASM: .section ".bss.$s7section2g1_Wz"
39-
// ASM: $s7section2g1_Wz:
40-
// ASM: .section "__TEXT,__mysection"
36+
// ASM-NOT: .section
4137
// ASM: $s7section2g1Si_Sitvp:
42-
43-
// ASM: .section ".bss.$s7section2g2_Wz"
44-
// ASM: $s7section2g2_Wz:
45-
// ASM: .section "__TEXT,__mysection"
38+
// ASM-NOT: .section
4639
// ASM: $s7section2g2Sbvp:
47-
48-
// ASM: .section ".bss.$s7section2g3_Wz"
49-
// ASM: $s7section2g3_Wz:
50-
// ASM: .section "__TEXT,__mysection"
40+
// ASM-NOT: .section
5141
// ASM: $s7section2g3Sbvp:
52-
53-
// ASM: .section ".bss.$s7section2g4_Wz"
54-
// ASM: $s7section2g4_Wz:
55-
// ASM: .section "__TEXT,__mysection"
42+
// ASM-NOT: .section
5643
// ASM: $s7section2g4SpySiGSgvp:
57-
58-
// ASM: .section ".bss.$s7section2g5_Wz"
59-
// ASM: $s7section2g5_Wz:
60-
// ASM: .section "__TEXT,__mysection"
44+
// ASM-NOT: .section
6145
// ASM: $s7section2g5SpySiGSgvp:

utils/build-presets.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,12 @@ mixin-preset=
888888
mixin_lightweight_assertions,no-stdlib-asserts
889889
buildbot_linux_base
890890

891+
[preset: buildbot_linux_crosscompile_wasm]
892+
mixin-preset=buildbot_linux
893+
894+
llvm-targets-to-build=X86;ARM;AArch64;WebAssembly
895+
build-wasm-stdlib
896+
891897
[preset: buildbot_linux,no_assertions]
892898
mixin-preset=buildbot_linux_base
893899

@@ -909,6 +915,7 @@ skip-test-libicu
909915
skip-test-indexstore-db
910916
skip-test-sourcekit-lsp
911917
skip-test-swiftdocc
918+
skip-test-wasm-stdlib
912919

913920
# Linux package with out test
914921
[preset: buildbot_linux,no_test]

utils/build_swift/build_swift/driver_arguments.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,9 @@ def create_argument_parser():
750750
option(['--build-minimal-stdlib'], toggle_true('build_minimalstdlib'),
751751
help='build the \'minimal\' freestanding stdlib variant into a '
752752
'separate build directory ')
753+
option(['--build-wasm-stdlib'], toggle_true('build_wasmstdlib'),
754+
help='build the stdlib for WebAssembly target into a'
755+
'separate build directory ')
753756

754757
option('--xctest', toggle_true('build_xctest'),
755758
help='build xctest')
@@ -1251,6 +1254,8 @@ def create_argument_parser():
12511254
help='skip testing swift_inspect')
12521255
option('--skip-test-swiftdocc', toggle_false('test_swiftdocc'),
12531256
help='skip testing swift-docc')
1257+
option('--skip-test-wasm-stdlib', toggle_false('test_wasmstdlib'),
1258+
help='skip testing stdlib for WebAssembly')
12541259

12551260
# -------------------------------------------------------------------------
12561261
in_group('Build settings specific for LLVM')

utils/build_swift/tests/expected_options.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@
128128
'build_watchos_device': False,
129129
'build_watchos_simulator': False,
130130
'build_xctest': False,
131+
'build_wasmstdlib': False,
131132
'cmake_c_launcher': None,
132133
'cmake_cxx_launcher': None,
133134
'clang_compiler_version': None,
@@ -293,6 +294,7 @@
293294
'test_swiftevolve': False,
294295
'test_swiftdocc': False,
295296
'test_toolchainbenchmarks': False,
297+
'test_wasmstdlib': True,
296298
'tvos': False,
297299
'tvos_all': False,
298300
'validation_test': None,
@@ -544,6 +546,7 @@ class BuildScriptImplOption(_BaseOption):
544546
SetTrueOption('--swiftevolve', dest='build_swiftevolve'),
545547
SetTrueOption('--swiftdocc', dest='build_swiftdocc'),
546548
SetTrueOption('--build-minimal-stdlib', dest='build_minimalstdlib'),
549+
SetTrueOption('--build-wasm-stdlib', dest='build_wasmstdlib'),
547550
SetTrueOption('-B', dest='benchmark'),
548551
SetTrueOption('-S', dest='skip_build'),
549552
SetTrueOption('-b', dest='build_llbuild'),
@@ -710,6 +713,8 @@ class BuildScriptImplOption(_BaseOption):
710713
dest='test_toolchainbenchmarks'),
711714
DisableOption('--skip-test-swift-inspect',
712715
dest='test_swift_inspect'),
716+
DisableOption('--skip-test-wasm-stdlib',
717+
dest='test_wasmstdlib'),
713718
DisableOption('--skip-build-clang-tools-extra',
714719
dest='build_clang_tools_extra'),
715720
DisableOption('--skip-build-libxml2', dest='build_libxml2'),

utils/swift_build_support/swift_build_support/build_script_invocation.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -666,6 +666,12 @@ def compute_product_pipelines(self):
666666
is_enabled=self.args.install_swiftdocc)
667667
builder.add_product(products.MinimalStdlib,
668668
is_enabled=self.args.build_minimalstdlib)
669+
builder.add_product(products.WASILibc,
670+
is_enabled=self.args.build_wasmstdlib)
671+
builder.add_product(products.WasmLLVMRuntimeLibs,
672+
is_enabled=self.args.build_wasmstdlib)
673+
builder.add_product(products.WasmStdlib,
674+
is_enabled=self.args.build_wasmstdlib)
669675

670676
# Keep SwiftDriver at last.
671677
# swift-driver's integration with the build scripts is not fully

utils/swift_build_support/swift_build_support/products/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
from .swiftpm import SwiftPM
3939
from .swiftsyntax import SwiftSyntax
4040
from .tsan_libdispatch import TSanLibDispatch
41+
from .wasisysroot import WASILibc, WasmLLVMRuntimeLibs
42+
from .wasmstdlib import WasmStdlib
4143
from .xctest import XCTest
4244
from .zlib import Zlib
4345

@@ -71,5 +73,8 @@
7173
'Benchmarks',
7274
'TSanLibDispatch',
7375
'SwiftDocC',
74-
'SwiftDocCRender'
76+
'SwiftDocCRender',
77+
'WASILibc',
78+
'WasmLLVMRuntimeLibs',
79+
'WasmStdlib'
7580
]
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
# swift_build_support/products/wasisysroot.py -------------------*- python -*-
2+
#
3+
# This source file is part of the Swift.org open source project
4+
#
5+
# Copyright (c) 2023 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+
import multiprocessing
14+
import os
15+
16+
from . import cmake_product
17+
from . import llvm
18+
from . import product
19+
from .. import shell
20+
21+
22+
class WASILibc(product.Product):
23+
@classmethod
24+
def product_source_name(cls):
25+
return "wasi-libc"
26+
27+
@classmethod
28+
def is_build_script_impl_product(cls):
29+
return False
30+
31+
@classmethod
32+
def is_before_build_script_impl_product(cls):
33+
return False
34+
35+
def should_build(self, host_target):
36+
# wasi-libc should always be built if standard library is being built for
37+
# WebAssembly.
38+
return self.args.build_wasmstdlib
39+
40+
def should_test(self, host_target):
41+
return False
42+
43+
def should_install(self, host_target):
44+
return False
45+
46+
def build(self, host_target):
47+
build_root = os.path.dirname(self.build_dir)
48+
llvm_build_dir = os.path.join('..', build_root, '%s-%s' % ('llvm', host_target))
49+
build_jobs = self.args.build_jobs or multiprocessing.cpu_count()
50+
51+
sysroot_build_dir = WASILibc.sysroot_build_path(build_root, host_target)
52+
# FIXME: Manually create an empty dir that is usually created during
53+
# check-symbols. The directory is required during sysroot installation step.
54+
os.makedirs(os.path.join(sysroot_build_dir, "share"), exist_ok=True)
55+
56+
shell.call([
57+
'make', 'install',
58+
'-j', str(build_jobs),
59+
# FIXME: wasi-libc's pre-defined macro list does not expect
60+
# `__FPCLASS_XXX`, which is introduced by the LLVM 17, yet.
61+
# So skip the symbol check step by treating the phony target
62+
# as very old file.
63+
# https://github.com/llvm/llvm-project/commit/7dd387d2971d7759cadfffeb2082439f6c7ddd49
64+
'--old-file=check-symbols',
65+
'-C', self.source_dir,
66+
'OBJDIR=' + os.path.join(self.build_dir, 'obj'),
67+
'SYSROOT=' + sysroot_build_dir,
68+
'INSTALL_DIR=' + WASILibc.sysroot_install_path(build_root),
69+
'CC=' + os.path.join(llvm_build_dir, 'bin', 'clang'),
70+
'AR=' + os.path.join(llvm_build_dir, 'bin', 'llvm-ar'),
71+
'NM=' + os.path.join(llvm_build_dir, 'bin', 'llvm-nm'),
72+
])
73+
74+
@classmethod
75+
def get_dependencies(cls):
76+
return [llvm.LLVM]
77+
78+
@classmethod
79+
def sysroot_build_path(cls, build_root, host_target):
80+
"""
81+
Returns the path to the sysroot build directory, which contains only the
82+
artifacts of wasi-libc (Not including the artifacts of LLVM runtimes).
83+
"""
84+
return os.path.join(build_root,
85+
'%s-%s' % (cls.product_name(), host_target), 'sysroot')
86+
87+
@classmethod
88+
def sysroot_install_path(cls, build_root):
89+
"""
90+
Returns the path to the sysroot install directory, which contains artifacts
91+
of wasi-libc and LLVM runtimes.
92+
"""
93+
return os.path.join(build_root, 'wasi-sysroot')
94+
95+
96+
class WasmLLVMRuntimeLibs(cmake_product.CMakeProduct):
97+
@classmethod
98+
def product_source_name(cls):
99+
return os.path.join("llvm-project", "runtimes")
100+
101+
@classmethod
102+
def is_build_script_impl_product(cls):
103+
return False
104+
105+
@classmethod
106+
def is_before_build_script_impl_product(cls):
107+
return False
108+
109+
def should_build(self, host_target):
110+
# LLVM runtime libraries should always be built for WebAssembly
111+
# if standard library is being built for WebAssembly.
112+
return self.args.build_wasmstdlib
113+
114+
def should_test(self, host_target):
115+
return False
116+
117+
def should_install(self, host_target):
118+
return False
119+
120+
def build(self, host_target):
121+
build_root = os.path.dirname(self.build_dir)
122+
llvm_build_dir = os.path.join('..', build_root, '%s-%s' % ('llvm', host_target))
123+
124+
self.cmake_options.define('CMAKE_SYSROOT:PATH',
125+
WASILibc.sysroot_build_path(build_root, host_target))
126+
self.cmake_options.define('LLVM_ENABLE_RUNTIMES:STRING',
127+
'libcxx;libcxxabi;compiler-rt')
128+
self.cmake_options.define('LIBCXX_LIBDIR_SUFFIX:STRING', '/wasm32-wasi')
129+
self.cmake_options.define('LIBCXXABI_LIBDIR_SUFFIX:STRING', '/wasm32-wasi')
130+
self.cmake_options.define('CMAKE_STAGING_PREFIX:PATH', '/')
131+
132+
self.cmake_options.define('COMPILER_RT_DEFAULT_TARGET_ARCH:STRING', 'wasm32')
133+
self.cmake_options.define('COMPILER_RT_DEFAULT_TARGET_ONLY:BOOL', 'TRUE')
134+
self.cmake_options.define('COMPILER_RT_BAREMETAL_BUILD:BOOL', 'TRUE')
135+
self.cmake_options.define('COMPILER_RT_BUILD_XRAY:BOOL', 'FALSE')
136+
self.cmake_options.define('COMPILER_RT_INCLUDE_TESTS:BOOL', 'FALSE')
137+
self.cmake_options.define('COMPILER_RT_HAS_FPIC_FLAG:BOOL', 'FALSE')
138+
self.cmake_options.define('COMPILER_RT_EXCLUDE_ATOMIC_BUILTIN:BOOL', 'FALSE')
139+
self.cmake_options.define('COMPILER_RT_OS_DIR:STRING', 'wasi')
140+
141+
self.cmake_options.define('CMAKE_C_COMPILER_WORKS:BOOL', 'TRUE')
142+
self.cmake_options.define('CMAKE_CXX_COMPILER_WORKS:BOOL', 'TRUE')
143+
144+
self.cmake_options.define('CMAKE_SYSTEM_NAME:STRING', 'WASI')
145+
self.cmake_options.define('CMAKE_SYSTEM_PROCESSOR:STRING', 'wasm32')
146+
self.cmake_options.define('CMAKE_AR:FILEPATH',
147+
os.path.join(llvm_build_dir, 'bin', 'llvm-ar'))
148+
self.cmake_options.define('CMAKE_RANLIB:FILEPATH',
149+
os.path.join(llvm_build_dir, 'bin', 'llvm-ranlib'))
150+
self.cmake_options.define('CMAKE_C_COMPILER:FILEPATH',
151+
os.path.join(llvm_build_dir, 'bin', 'clang'))
152+
self.cmake_options.define('CMAKE_CXX_COMPILER:STRING',
153+
os.path.join(llvm_build_dir, 'bin', 'clang++'))
154+
# Explicitly disable exceptions even though it's usually implicitly disabled by
155+
# LIBCXX_ENABLE_EXCEPTIONS because the CMake feature check fails to detect
156+
# -fno-exceptions support in clang due to missing compiler-rt while configuring
157+
# as mono project.
158+
self.cmake_options.define('CMAKE_CXX_FLAGS:STRING', '-fno-exceptions')
159+
160+
self.cmake_options.define('CMAKE_C_COMPILER_TARGET:STRING', 'wasm32-wasi')
161+
self.cmake_options.define('CMAKE_CXX_COMPILER_TARGET:STRING', 'wasm32-wasi')
162+
163+
self.cmake_options.define('CXX_SUPPORTS_CXX11:BOOL', 'TRUE')
164+
165+
self.cmake_options.define('LIBCXX_ENABLE_THREADS:BOOL', 'FALSE')
166+
self.cmake_options.define('LIBCXX_HAS_PTHREAD_API:BOOL', 'FALSE')
167+
self.cmake_options.define('LIBCXX_HAS_EXTERNAL_THREAD_API:BOOL', 'FALSE')
168+
self.cmake_options.define('LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY:BOOL', 'FALSE')
169+
self.cmake_options.define('LIBCXX_HAS_WIN32_THREAD_API:BOOL', 'FALSE')
170+
self.cmake_options.define('LIBCXX_ENABLE_SHARED:BOOL', 'FALSE')
171+
self.cmake_options.define('LIBCXX_ENABLE_EXPERIMENTAL_LIBRARY:BOOL', 'FALSE')
172+
self.cmake_options.define('LIBCXX_ENABLE_EXCEPTIONS:BOOL', 'FALSE')
173+
self.cmake_options.define('LIBCXX_ENABLE_FILESYSTEM:BOOL', 'FALSE')
174+
self.cmake_options.define('LIBCXX_CXX_ABI', 'libcxxabi')
175+
self.cmake_options.define('LIBCXX_HAS_MUSL_LIBC:BOOL', 'TRUE')
176+
177+
self.cmake_options.define('LIBCXX_ABI_VERSION', '2')
178+
self.cmake_options.define('LIBCXXABI_ENABLE_EXCEPTIONS:BOOL', 'FALSE')
179+
self.cmake_options.define('LIBCXXABI_ENABLE_SHARED:BOOL', 'FALSE')
180+
self.cmake_options.define('LIBCXXABI_SILENT_TERMINATE:BOOL', 'TRUE')
181+
self.cmake_options.define('LIBCXXABI_ENABLE_THREADS:BOOL', 'FALSE')
182+
self.cmake_options.define('LIBCXXABI_HAS_PTHREAD_API:BOOL', 'FALSE')
183+
self.cmake_options.define('LIBCXXABI_HAS_EXTERNAL_THREAD_API:BOOL', 'FALSE')
184+
self.cmake_options.define('LIBCXXABI_BUILD_EXTERNAL_THREAD_LIBRARY:BOOL',
185+
'FALSE')
186+
self.cmake_options.define('LIBCXXABI_HAS_WIN32_THREAD_API:BOOL', 'FALSE')
187+
self.cmake_options.define('LIBCXXABI_ENABLE_PIC:BOOL', 'FALSE')
188+
self.cmake_options.define('UNIX:BOOL', 'TRUE')
189+
190+
self.build_with_cmake([], self.args.build_variant, [],
191+
prefer_just_built_toolchain=True)
192+
self.install_with_cmake(
193+
["install"], WASILibc.sysroot_install_path(build_root))
194+
195+
@classmethod
196+
def get_dependencies(cls):
197+
return [WASILibc, llvm.LLVM]

0 commit comments

Comments
 (0)