Add basic Webassembly support via Emscripten.

pull/5774/head
Jussi Pakkanen 5 yıl önce
ebeveyn ddbf60f86d
işleme f41bdae368
  1. 19
      cross/wasm.txt
  2. 4
      docs/markdown/Reference-tables.md
  3. 5
      docs/markdown/snippets/wasm.md
  4. 2
      mesonbuild/build.py
  5. 2
      mesonbuild/compilers/__init__.py
  6. 25
      mesonbuild/compilers/c.py
  7. 1
      mesonbuild/compilers/compilers.py
  8. 35
      mesonbuild/compilers/cpp.py
  9. 3
      mesonbuild/envconfig.py
  10. 7
      mesonbuild/environment.py
  11. 7
      mesonbuild/minstall.py
  12. 7
      test cases/wasm/1 basic/hello.cpp
  13. 8
      test cases/wasm/1 basic/hello.html
  14. 3
      test cases/wasm/1 basic/meson.build

@ -0,0 +1,19 @@
[binaries]
c = '/home/jpakkane/emsdk/fastcomp/emscripten/emcc'
cpp = '/home/jpakkane/emsdk/fastcomp/emscripten/em++'
ar = '/home/jpakkane/emsdk/fastcomp/emscripten/emar'
[properties]
c_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1']
c_link_args = ['-s','EXPORT_ALL=1']
cpp_args = ['-s', 'WASM=1', '-s', 'EXPORT_ALL=1']
cpp_link_args = ['-s', 'EXPORT_ALL=1']
[host_machine]
system = 'emscripten'
cpu_family = 'wasm32'
cpu = 'wasm32'
endian = 'little'

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

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

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

@ -126,6 +126,7 @@ from .c import (
ClangClCCompiler,
GnuCCompiler,
ElbrusCCompiler,
EmscriptenCCompiler,
IntelCCompiler,
IntelClCCompiler,
PGICCompiler,
@ -140,6 +141,7 @@ from .cpp import (
ClangClCPPCompiler,
GnuCPPCompiler,
ElbrusCPPCompiler,
EmscriptenCPPCompiler,
IntelCPPCompiler,
IntelClCPPCompiler,
PGICPPCompiler,

@ -119,6 +119,31 @@ class ClangCCompiler(ClangCompiler, CCompiler):
return basic
class EmscriptenCCompiler(ClangCCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
if not is_cross:
raise MesonException('Emscripten compiler can only be used for cross compilation.')
ClangCCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, **kwargs)
self.id = 'emscripten'
def get_option_link_args(self, options):
return []
def get_linker_always_args(self):
return []
def get_asneeded_args(self):
return []
def get_lundef_args(self):
return []
def build_rpath_args(self, *args, **kwargs):
return []
def get_soname_args(self, *args, **kwargs):
raise MesonException('Emscripten does not support shared libraries.')
class ArmclangCCompiler(ArmclangCompiler, CCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
CCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)

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

@ -131,7 +131,7 @@ class CPPCompiler(CLikeCompiler, Compiler):
}
# Currently, remapping is only supported for Clang, Elbrus and GCC
assert(self.id in frozenset(['clang', 'lcc', 'gcc']))
assert(self.id in frozenset(['clang', 'lcc', 'gcc', 'emscripten']))
if cpp_std not in CPP_FALLBACKS:
# 'c++03' and 'c++98' don't have fallback types
@ -183,6 +183,39 @@ class ClangCPPCompiler(ClangCompiler, CPPCompiler):
return ['-lstdc++']
class EmscriptenCPPCompiler(ClangCPPCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
if not is_cross:
raise MesonException('Emscripten compiler can only be used for cross compilation.')
ClangCPPCompiler.__init__(self, exelist, version, compiler_type, for_machine, is_cross, exe_wrapper, **kwargs)
self.id = 'emscripten'
def get_option_compile_args(self, options):
args = []
std = options['cpp_std']
if std.value != 'none':
args.append(self._find_best_cpp_std(std.value))
return args
def get_option_link_args(self, options):
return []
def get_linker_always_args(self):
return []
def get_asneeded_args(self):
return []
def get_lundef_args(self):
return []
def build_rpath_args(self, *args, **kwargs):
return []
def get_soname_args(self, *args, **kwargs):
raise MesonException('Emscripten does not support shared libraries.')
class ArmclangCPPCompiler(ArmclangCompiler, CPPCompiler):
def __init__(self, exelist, version, compiler_type, for_machine: MachineChoice, is_cross, exe_wrapper=None, **kwargs):
CPPCompiler.__init__(self, exelist, version, for_machine, is_cross, exe_wrapper, **kwargs)

@ -53,6 +53,8 @@ known_cpu_families = (
's390x',
'sparc',
'sparc64',
'wasm32',
'wasm64',
'x86',
'x86_64'
)
@ -66,6 +68,7 @@ CPU_FAMILES_64_BIT = [
'ppc64',
'riscv64',
'sparc64',
'wasm64',
'x86_64',
]

@ -60,6 +60,8 @@ from .compilers import (
ElbrusCCompiler,
ElbrusCPPCompiler,
ElbrusFortranCompiler,
EmscriptenCCompiler,
EmscriptenCPPCompiler,
IntelCCompiler,
IntelCPPCompiler,
IntelClCCompiler,
@ -707,6 +709,11 @@ class Environment:
cls = GnuCCompiler if lang == 'c' else GnuCPPCompiler
return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, defines, full_version=full_version)
if 'Emscripten' in out:
cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler
compiler_type = CompilerType.CLANG_EMSCRIPTEN
return cls(ccache + compiler, version, compiler_type, for_machine, is_cross, exe_wrap, full_version=full_version)
if 'armclang' in out:
# The compiler version is not present in the first line of output,
# instead it is present in second line, startswith 'Component:'.

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

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

@ -0,0 +1,8 @@
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="hello.js"></script>
</body>
</html>

@ -0,0 +1,3 @@
project('emcctest', 'cpp')
executable('hello', 'hello.cpp')
Yükleniyor…
İptal
Kaydet