Browse Source

Add basic Webassembly support via Emscripten.

Jussi Pakkanen 3 months ago
parent
commit
f41bdae368

+ 19
- 0
cross/wasm.txt View File

@@ -0,0 +1,19 @@
1
+[binaries]
2
+c = '/home/jpakkane/emsdk/fastcomp/emscripten/emcc'
3
+cpp = '/home/jpakkane/emsdk/fastcomp/emscripten/em++'
4
+ar = '/home/jpakkane/emsdk/fastcomp/emscripten/emar'
5
+
6
+[properties]
7
+
8
+c_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1']
9
+c_link_args = ['-s','EXPORT_ALL=1']
10
+cpp_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1']
11
+cpp_link_args = ['-s', 'EXPORT_ALL=1']
12
+
13
+[host_machine]
14
+
15
+system = 'emscripten'
16
+cpu_family = 'wasm32'
17
+cpu = 'wasm32'
18
+endian = 'little'
19
+

+ 4
- 0
docs/markdown/Reference-tables.md View File

@@ -13,6 +13,7 @@ These are return values of the `get_id` (Compiler family) and
13 13
 | clang     | The Clang compiler               | gcc             |
14 14
 | clang-cl  | The Clang compiler (MSVC compatible driver) | msvc |
15 15
 | dmd       | D lang reference compiler        |                 |
16
+| emscripten| Emscripten WASM compiler         |                 |
16 17
 | flang     | Flang Fortran compiler           |                 |
17 18
 | g95       | The G95 Fortran compiler         |                 |
18 19
 | gcc       | The GNU Compiler Collection      | gcc             |
@@ -66,6 +67,8 @@ set in the cross file.
66 67
 | s390x               | IBM zSystem s390x     |
67 68
 | sparc               | 32 bit SPARC          |
68 69
 | sparc64             | SPARC v9 processor    |
70
+| wasm32              | 32 bit Webassembly    |
71
+| wasm64              | 64 bit Webassembly    |
69 72
 | x86                 | 32 bit x86 processor  |
70 73
 | x86_64              | 64 bit x86 processor  |
71 74
 
@@ -86,6 +89,7 @@ These are provided by the `.system()` method call.
86 89
 | cygwin              | The Cygwin environment for Windows |
87 90
 | darwin              | Either OSX or iOS |
88 91
 | dragonfly           | DragonFly BSD |
92
+| emscripten          | Emscripten's Javascript environment |
89 93
 | freebsd             | FreeBSD and its derivatives |
90 94
 | gnu                 | GNU Hurd |
91 95
 | haiku               | |

+ 5
- 0
docs/markdown/snippets/wasm.md View File

@@ -0,0 +1,5 @@
1
+## Experimental Webassembly support via Emscripten
2
+
3
+Meson now supports compiling code to Webassembly using the Emscripten
4
+compiler. As with most things regarding Webassembly, this support is
5
+subject to change.

+ 2
- 0
mesonbuild/build.py View File

@@ -1432,6 +1432,8 @@ class Executable(BuildTarget):
1432 1432
             # Executable for Windows or C#/Mono
1433 1433
             if machine.is_windows() or machine.is_cygwin() or 'cs' in self.compilers:
1434 1434
                 self.suffix = 'exe'
1435
+            elif machine.system.startswith('wasm') or machine.system == 'emscripten':
1436
+                self.suffix = 'js'
1435 1437
             elif ('c' in self.compilers and self.compilers['c'].get_id().startswith('arm') or
1436 1438
                   'cpp' in self.compilers and self.compilers['cpp'].get_id().startswith('arm')):
1437 1439
                 self.suffix = 'axf'

+ 2
- 0
mesonbuild/compilers/__init__.py View File

@@ -126,6 +126,7 @@ from .c import (
126 126
     ClangClCCompiler,
127 127
     GnuCCompiler,
128 128
     ElbrusCCompiler,
129
+    EmscriptenCCompiler,
129 130
     IntelCCompiler,
130 131
     IntelClCCompiler,
131 132
     PGICCompiler,
@@ -140,6 +141,7 @@ from .cpp import (
140 141
     ClangClCPPCompiler,
141 142
     GnuCPPCompiler,
142 143
     ElbrusCPPCompiler,
144
+    EmscriptenCPPCompiler,
143 145
     IntelCPPCompiler,
144 146
     IntelClCPPCompiler,
145 147
     PGICPPCompiler,

+ 25
- 0
mesonbuild/compilers/c.py View File

@@ -119,6 +119,31 @@ class ClangCCompiler(ClangCompiler, CCompiler):
119 119
         return basic
120 120
 
121 121
 
122
+class EmscriptenCCompiler(ClangCCompiler):
123
+    def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
124
+        if not is_cross:
125
+            raise MesonException('Emscripten compiler can only be used for cross compilation.')
126
+        ClangCCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, **kwargs)
127
+        self.id = 'emscripten'
128
+
129
+    def get_option_link_args(self, options):
130
+        return []
131
+
132
+    def get_linker_always_args(self):
133
+        return []
134
+
135
+    def get_asneeded_args(self):
136
+        return []
137
+
138
+    def get_lundef_args(self):
139
+        return []
140
+
141
+    def build_rpath_args(self, *args, **kwargs):
142
+        return []
143
+
144
+    def get_soname_args(self, *args, **kwargs):
145
+        raise MesonException('Emscripten does not support shared libraries.')
146
+
122 147
 class ArmclangCCompiler(ArmclangCompiler, CCompiler):
123 148
     def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
124 149
         CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)

+ 1
- 0
mesonbuild/compilers/compilers.py View File

@@ -1204,6 +1204,7 @@ class CompilerType(enum.Enum):
1204 1204
     CLANG_STANDARD = 10
1205 1205
     CLANG_OSX = 11
1206 1206
     CLANG_MINGW = 12
1207
+    CLANG_EMSCRIPTEN = 13
1207 1208
     # Possibly clang-cl?
1208 1209
 
1209 1210
     ICC_STANDARD = 20

+ 34
- 1
mesonbuild/compilers/cpp.py View File

@@ -131,7 +131,7 @@ class CPPCompiler(CLikeCompiler, Compiler):
131 131
         }
132 132
 
133 133
         # Currently, remapping is only supported for Clang, Elbrus and GCC
134
-        assert(self.id in frozenset(['clang', 'lcc', 'gcc']))
134
+        assert(self.id in frozenset(['clang', 'lcc', 'gcc', 'emscripten']))
135 135
 
136 136
         if cpp_std not in CPP_FALLBACKS:
137 137
             # 'c++03' and 'c++98' don't have fallback types
@@ -183,6 +183,39 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
183 183
         return ['-lstdc++']
184 184
 
185 185
 
186
+class EmscriptenCPPCompiler(ClangCPPCompiler):
187
+    def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
188
+        if not is_cross:
189
+            raise MesonException('Emscripten compiler can only be used for cross compilation.')
190
+        ClangCPPCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, **kwargs)
191
+        self.id = 'emscripten'
192
+
193
+    def get_option_compile_args(self, options):
194
+        args = []
195
+        std = options['cpp_std']
196
+        if std.value != 'none':
197
+            args.append(self._find_best_cpp_std(std.value))
198
+        return args
199
+
200
+    def get_option_link_args(self, options):
201
+        return []
202
+
203
+    def get_linker_always_args(self):
204
+        return []
205
+
206
+    def get_asneeded_args(self):
207
+        return []
208
+
209
+    def get_lundef_args(self):
210
+        return []
211
+
212
+    def build_rpath_args(self, *args, **kwargs):
213
+        return []
214
+
215
+    def get_soname_args(self, *args, **kwargs):
216
+        raise MesonException('Emscripten does not support shared libraries.')
217
+
218
+
186 219
 class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
187 220
     def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
188 221
         CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)

+ 3
- 0
mesonbuild/envconfig.py View File

@@ -53,6 +53,8 @@ known_cpu_families = (
53 53
     's390x',
54 54
     'sparc',
55 55
     'sparc64',
56
+    'wasm32',
57
+    'wasm64',
56 58
     'x86',
57 59
     'x86_64'
58 60
 )
@@ -66,6 +68,7 @@ CPU_FAMILES_64_BIT = [
66 68
     'ppc64',
67 69
     'riscv64',
68 70
     'sparc64',
71
+    'wasm64',
69 72
     'x86_64',
70 73
 ]
71 74
 

+ 7
- 0
mesonbuild/environment.py View File

@@ -60,6 +60,8 @@ from .compilers import (
60 60
     ElbrusCCompiler,
61 61
     ElbrusCPPCompiler,
62 62
     ElbrusFortranCompiler,
63
+    EmscriptenCCompiler,
64
+    EmscriptenCPPCompiler,
63 65
     IntelCCompiler,
64 66
     IntelCPPCompiler,
65 67
     IntelClCCompiler,
@@ -707,6 +709,11 @@ class Environment:
707 709
                     cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
708 710
                 return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version)
709 711
 
712
+            if 'Emscripten' in out:
713
+                cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler
714
+                compiler_type = CompilerType.CLANG_EMSCRIPTEN
715
+                return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version)
716
+
710 717
             if 'armclang' in out:
711 718
                 # The compiler version is not present in the first line of output,
712 719
                 # instead it is present in second line, startswith 'Component:'.

+ 7
- 0
mesonbuild/minstall.py View File

@@ -465,6 +465,13 @@ class Installer:
465 465
                     pdb_outname = os.path.splitext(outname)[0] + '.pdb'
466 466
                     self.do_copyfile(pdb_filename, pdb_outname)
467 467
                     set_mode(pdb_outname, install_mode, d.install_umask)
468
+                if fname.endswith('.js'):
469
+                    # Emscripten outputs js files and optionally a wasm file.
470
+                    # If one was generated, install it as well.
471
+                    wasm_source = os.path.splitext(fname)[0] + '.wasm'
472
+                    if os.path.exists(wasm_source):
473
+                        wasm_output = os.path.splitext(outname)[0] + '.wasm'
474
+                        self.do_copyfile(wasm_source, wasm_output)
468 475
             elif os.path.isdir(fname):
469 476
                 fname = os.path.join(d.build_dir, fname.rstrip('/'))
470 477
                 outname = os.path.join(outdir, os.path.basename(fname))

+ 7
- 0
test cases/wasm/1 basic/hello.cpp View File

@@ -0,0 +1,7 @@
1
+#include<iostream>
2
+
3
+int main() {
4
+  std::cout << "Hello World" << std::endl;
5
+  return 0;
6
+}
7
+

+ 8
- 0
test cases/wasm/1 basic/hello.html View File

@@ -0,0 +1,8 @@
1
+<html>
2
+  <head>
3
+    <meta charset="utf-8">
4
+  </head>
5
+  <body>
6
+    <script src="hello.js"></script>
7
+  </body>
8
+</html>

+ 3
- 0
test cases/wasm/1 basic/meson.build View File

@@ -0,0 +1,3 @@
1
+project('emcctest', 'cpp')
2
+
3
+executable('hello', 'hello.cpp')

Loading…
Cancel
Save