From 64f3174daa54a2ef8cf63df94921919717057243 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 24 Feb 2020 10:30:05 -0800 Subject: compilers/emcc: Fix inheritance order Sot hat the BasicLinkerIsCompilerMixin comes before ClangCCompiler, which hides its "call the linker" methods, as emcc doesn't have a separate linker. --- mesonbuild/compilers/cpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mesonbuild/compilers/cpp.py') diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index bdca5962d..f6f4cfc26 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -201,7 +201,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler): pass -class EmscriptenCPPCompiler(LinkerEnvVarsMixin, EmscriptenMixin, BasicLinkerIsCompilerMixin, ClangCPPCompiler): +class EmscriptenCPPCompiler(BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, EmscriptenMixin, ClangCPPCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): if not is_cross: -- cgit v1.2.3 From 771b0d3ffbc7b034b436d4ad27be7d0a1da6b3cd Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Mon, 24 Feb 2020 10:55:31 -0800 Subject: compilers/mixins/emscripten: Implement thread support Emscripten has pthread support (as well as C++ threads), but we don't currently implement them. This fixes that by adding the necessary code. The one thing I'm not sure about is setting the pool size. The docs suggest that you really want to do this to ensure that your code works correctly, but the number should really be configurable, not sure how to set that. Fixes #6684 --- docs/markdown/Builtin-options.md | 34 ++++++++++++++++------------ docs/markdown/snippets/emscripten_threads.md | 6 +++++ mesonbuild/compilers/c.py | 2 +- mesonbuild/compilers/cpp.py | 2 +- mesonbuild/compilers/mixins/emscripten.py | 26 +++++++++++++++++++++ test cases/wasm/2 threads/meson.build | 10 ++++++++ test cases/wasm/2 threads/threads.c | 21 +++++++++++++++++ test cases/wasm/2 threads/threads.cpp | 13 +++++++++++ 8 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 docs/markdown/snippets/emscripten_threads.md create mode 100644 test cases/wasm/2 threads/meson.build create mode 100644 test cases/wasm/2 threads/threads.c create mode 100644 test cases/wasm/2 threads/threads.cpp (limited to 'mesonbuild/compilers/cpp.py') diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md index 067966fc9..ac40263d4 100644 --- a/docs/markdown/Builtin-options.md +++ b/docs/markdown/Builtin-options.md @@ -134,20 +134,22 @@ The following options are available. Note that both the options themselves and the possible values they can take will depend on the target platform or compiler being used: -| Option | Default value | Possible values | Description | -| ------ | ------------- | --------------- | ----------- | -| c_args | | free-form comma-separated list | C compile arguments to use | -| c_link_args | | free-form comma-separated list | C link arguments to use | -| c_std | none | none, c89, c99, c11, c17, c18, gnu89, gnu99, gnu11, gnu17, gnu18 | C language standard to use | -| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | -| cpp_args | | free-form comma-separated list | C++ compile arguments to use | -| cpp_link_args| | free-form comma-separated list | C++ link arguments to use | -| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17,
c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z,
vc++14, vc++17, vc++latest | C++ language standard to use | -| cpp_debugstl | false | true, false | C++ STL debug mode | -| cpp_eh | default | none, default, a, s, sc | C++ exception handling type | -| cpp_rtti | true | true, false | Whether to enable RTTI (runtime type identification) | -| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | -| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use | +| Option | Default value | Possible values | Description | +| ------ | ------------- | --------------- | ----------- | +| c_args | | free-form comma-separated list | C compile arguments to use | +| c_link_args | | free-form comma-separated list | C link arguments to use | +| c_std | none | none, c89, c99, c11, c17, c18, gnu89, gnu99, gnu11, gnu17, gnu18 | C language standard to use | +| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | +| c_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads | +| cpp_args | | free-form comma-separated list | C++ compile arguments to use | +| cpp_link_args | | free-form comma-separated list | C++ link arguments to use | +| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17,
c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z,
vc++14, vc++17, vc++latest | C++ language standard to use | +| cpp_debugstl | false | true, false | C++ STL debug mode | +| cpp_eh | default | none, default, a, s, sc | C++ exception handling type | +| cpp_rtti | true | true, false | Whether to enable RTTI (runtime type identification) | +| cpp_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads | +| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against | +| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use | The default values of `c_winlibs` and `cpp_winlibs` are in compiler-specific argument forms, but the libraries are: kernel32, user32, gdi32, winspool, @@ -162,3 +164,7 @@ while the `cpp_eh=[value]` will result in `/EH[value]`. Since *0.51.0* `cpp_eh=default` will result in `/EHsc` on MSVC. When using gcc-style compilers, nothing is passed (allowing exceptions to work), while `cpp_eh=none` passes `-fno-exceptions`. + +Since *0.54.0* The `_thread_count` option can be used to control the +value passed to `-s PTHREAD_POOL_SIZE` when using emcc. No other c/c++ +compiler supports this option. diff --git a/docs/markdown/snippets/emscripten_threads.md b/docs/markdown/snippets/emscripten_threads.md new file mode 100644 index 000000000..bdf808e26 --- /dev/null +++ b/docs/markdown/snippets/emscripten_threads.md @@ -0,0 +1,6 @@ +## Emscripten (emcc) now supports threads + +In addition to properly setting the compile and linker arguments, a new meson +builtin has been added to control the PTHREAD_POOL_SIZE option, +`-D_thread_count`, which may be set to any integer value greater than 0. +If it set to 0 then the PTHREAD_POOL_SIZE option will not be passed. diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index e27eb901d..f3ed9e82b 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -133,7 +133,7 @@ class AppleClangCCompiler(ClangCCompiler): _C18_VERSION = '>=11.0.0' -class EmscriptenCCompiler(BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, EmscriptenMixin, ClangCCompiler): +class EmscriptenCCompiler(EmscriptenMixin, BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, ClangCCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): if not is_cross: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index f6f4cfc26..2a244e9b1 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -201,7 +201,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler): pass -class EmscriptenCPPCompiler(BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, EmscriptenMixin, ClangCPPCompiler): +class EmscriptenCPPCompiler(EmscriptenMixin, BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, ClangCPPCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): if not is_cross: diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py index 36a757ae5..ee86ce4d3 100644 --- a/mesonbuild/compilers/mixins/emscripten.py +++ b/mesonbuild/compilers/mixins/emscripten.py @@ -17,8 +17,13 @@ import os.path import typing as T +from ... import coredata from ...mesonlib import MesonException +if T.TYPE_CHECKING: + from ..environment import Environment + + class EmscriptenMixin: def get_option_link_args(self, options): @@ -45,3 +50,24 @@ class EmscriptenMixin: else: suffix = 'wasm' return os.path.join(dirname, 'output.' + suffix) + + def thread_flags(self, env: 'Environment') -> T.List[str]: + return ['-s', 'USE_PTHREADS=1'] + + def thread_link_flags(self, env: 'Environment') -> T.List[str]: + args = ['-s', 'USE_PTHREADS=1'] + count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int + if count: + args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)]) + return args + + def get_options(self): + opts = super().get_options() + opts.update({ + '{}_thread_count'.format(self.language): coredata.UserIntegerOption( + 'Number of threads to use in web assembly, set to 0 to disable', + (0, None, 4), # Default was picked at random + ), + }) + + return opts diff --git a/test cases/wasm/2 threads/meson.build b/test cases/wasm/2 threads/meson.build new file mode 100644 index 000000000..cb682b877 --- /dev/null +++ b/test cases/wasm/2 threads/meson.build @@ -0,0 +1,10 @@ +project( + 'threads', + 'c', 'cpp', + default_options : ['cpp_std=c++11'], +) + +dep_threads = dependency('threads') + +executable('threads-c', 'threads.c', dependencies : dep_threads) +executable('threads-c++', 'threads.cpp', dependencies : dep_threads) diff --git a/test cases/wasm/2 threads/threads.c b/test cases/wasm/2 threads/threads.c new file mode 100644 index 000000000..e79bff170 --- /dev/null +++ b/test cases/wasm/2 threads/threads.c @@ -0,0 +1,21 @@ +#include +#include +#include + +void inthread(void * args) { + sleep(1); + printf("In thread\n"); +} + +int main() { +#ifdef __EMSCRIPTEN_PTHREADS__ + pthread_t thread_id; + printf("Before Thread\n"); + pthread_create(&thread_id, NULL, (void *)*inthread, NULL); + pthread_join(thread_id, NULL); + printf("After Thread\n"); + return 0; +#else +# error "threads not enabled\n" +#endif +} diff --git a/test cases/wasm/2 threads/threads.cpp b/test cases/wasm/2 threads/threads.cpp new file mode 100644 index 000000000..1caa73da3 --- /dev/null +++ b/test cases/wasm/2 threads/threads.cpp @@ -0,0 +1,13 @@ +#include +#include +#include + +int main(void) { + std::cout << "Before thread" << std::endl; + std::thread t([]() { + sleep(1); + std::cout << "In a thread." << std::endl; + }); + t.join(); + std::cout << "After thread" << std::endl; +} -- cgit v1.2.3 From 654f427759d5aa3be55d8929b18c17a2b8fcac69 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 25 Feb 2020 11:36:31 -0800 Subject: compilers/linkers: Add a representation for wasm-ld Emscripten does have a stand alone linker, wasm-ld. This patch adds the linker, adds detection for the linker, and removes the IsLinkerMixin for emscripten. This is a little more correct, and makes the code a lot cleaner and more robust. --- docs/markdown/Reference-tables.md | 3 ++- docs/markdown/snippets/wasm_ld.md | 5 +++++ mesonbuild/compilers/c.py | 4 ++-- mesonbuild/compilers/cpp.py | 4 ++-- mesonbuild/compilers/mixins/emscripten.py | 20 -------------------- mesonbuild/environment.py | 12 +++++++++++- mesonbuild/linkers.py | 29 +++++++++++++++++++++++++++++ 7 files changed, 51 insertions(+), 26 deletions(-) create mode 100644 docs/markdown/snippets/wasm_ld.md (limited to 'mesonbuild/compilers/cpp.py') diff --git a/docs/markdown/Reference-tables.md b/docs/markdown/Reference-tables.md index 9f432f0c8..59e252f19 100644 --- a/docs/markdown/Reference-tables.md +++ b/docs/markdown/Reference-tables.md @@ -37,10 +37,11 @@ These are return values of the `get_linker_id` method in a compiler object. | Value | Linker family | | ----- | --------------- | -| ld.bfd | The GNU linker | +| ld.bfd | The GNU linker | | ld.gold | The GNU gold linker | | ld.lld | The LLVM linker, with the GNU interface | | ld.solaris | Solaris and illumos | +| ld.wasm | emscripten's wasm-ld linker | | ld64 | Apple ld64 | | link | MSVC linker | | lld-link | The LLVM linker, with the MSVC interface | diff --git a/docs/markdown/snippets/wasm_ld.md b/docs/markdown/snippets/wasm_ld.md new file mode 100644 index 000000000..d47767c71 --- /dev/null +++ b/docs/markdown/snippets/wasm_ld.md @@ -0,0 +1,5 @@ +## Property support emscripten's wasm-ld + +Before 0.54.0 we treated emscripten as both compiler and linker, which isn't +really true. It does have a linker, called wasm-ld (meson's name is ld.wasm). +This is a special version of clang's lld. This will now be detected properly. diff --git a/mesonbuild/compilers/c.py b/mesonbuild/compilers/c.py index f3ed9e82b..e17d655db 100644 --- a/mesonbuild/compilers/c.py +++ b/mesonbuild/compilers/c.py @@ -27,7 +27,7 @@ from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler -from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin +from .mixins.islinker import LinkerEnvVarsMixin from .mixins.emscripten import EmscriptenMixin from .compilers import ( gnu_winlibs, @@ -133,7 +133,7 @@ class AppleClangCCompiler(ClangCCompiler): _C18_VERSION = '>=11.0.0' -class EmscriptenCCompiler(EmscriptenMixin, BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, ClangCCompiler): +class EmscriptenCCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): if not is_cross: diff --git a/mesonbuild/compilers/cpp.py b/mesonbuild/compilers/cpp.py index 2a244e9b1..db7875b93 100644 --- a/mesonbuild/compilers/cpp.py +++ b/mesonbuild/compilers/cpp.py @@ -36,7 +36,7 @@ from .mixins.intel import IntelGnuLikeCompiler, IntelVisualStudioLikeCompiler from .mixins.clang import ClangCompiler from .mixins.elbrus import ElbrusCompiler from .mixins.pgi import PGICompiler -from .mixins.islinker import BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin +from .mixins.islinker import LinkerEnvVarsMixin from .mixins.emscripten import EmscriptenMixin if T.TYPE_CHECKING: @@ -201,7 +201,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler): pass -class EmscriptenCPPCompiler(EmscriptenMixin, BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, ClangCPPCompiler): +class EmscriptenCPPCompiler(EmscriptenMixin, LinkerEnvVarsMixin, ClangCPPCompiler): def __init__(self, exelist, version, for_machine: MachineChoice, is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs): if not is_cross: diff --git a/mesonbuild/compilers/mixins/emscripten.py b/mesonbuild/compilers/mixins/emscripten.py index ee86ce4d3..10f4b25cc 100644 --- a/mesonbuild/compilers/mixins/emscripten.py +++ b/mesonbuild/compilers/mixins/emscripten.py @@ -18,7 +18,6 @@ import os.path import typing as T from ... import coredata -from ...mesonlib import MesonException if T.TYPE_CHECKING: from ..environment import Environment @@ -26,18 +25,6 @@ if T.TYPE_CHECKING: class EmscriptenMixin: - def get_option_link_args(self, options): - return [] - - def get_soname_args(self, *args, **kwargs): - raise MesonException('Emscripten does not support shared libraries.') - - def get_allow_undefined_link_args(self) -> T.List[str]: - return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0'] - - def get_linker_output_args(self, output: str) -> T.List[str]: - return ['-o', output] - def _get_compile_output(self, dirname, mode): # In pre-processor mode, the output is sent to stdout and discarded if mode == 'preprocess': @@ -54,13 +41,6 @@ class EmscriptenMixin: def thread_flags(self, env: 'Environment') -> T.List[str]: return ['-s', 'USE_PTHREADS=1'] - def thread_link_flags(self, env: 'Environment') -> T.List[str]: - args = ['-s', 'USE_PTHREADS=1'] - count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int - if count: - args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)]) - return args - def get_options(self): opts = super().get_options() opts.update({ diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py index 46bbea036..9e30f4755 100644 --- a/mesonbuild/environment.py +++ b/mesonbuild/environment.py @@ -58,6 +58,7 @@ from .linkers import ( XilinkDynamicLinker, CudaLinker, VisualStudioLikeLinkerMixin, + WASMDynamicLinker, ) from functools import lru_cache from .compilers import ( @@ -957,9 +958,18 @@ class Environment: if 'Emscripten' in out: cls = EmscriptenCCompiler if lang == 'c' else EmscriptenCPPCompiler self.coredata.add_lang_args(cls.language, cls, for_machine, self) + # emcc cannot be queried to get the version out of it (it + # ignores -Wl,--version and doesn't have an alternative). + # Further, wasm-id *is* lld and will return `LLD X.Y.Z` if you + # call `wasm-ld --version`, but a special version of lld that + # takes different options. + p, o, _ = Popen_safe(['wasm-ld', '--version']) + linker = WASMDynamicLinker( + compiler, for_machine, cls.LINKER_PREFIX, + [], version=search_version(o)) return cls( ccache + compiler, version, for_machine, is_cross, info, - exe_wrap, full_version=full_version) + exe_wrap, linker=linker, full_version=full_version) if 'armclang' in out: # The compiler version is not present in the first line of output, diff --git a/mesonbuild/linkers.py b/mesonbuild/linkers.py index 489525b77..73cdeefa7 100644 --- a/mesonbuild/linkers.py +++ b/mesonbuild/linkers.py @@ -693,6 +693,35 @@ class LLVMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, Dyna return [] +class WASMDynamicLinker(GnuLikeDynamicLinkerMixin, PosixDynamicLinkerMixin, DynamicLinker): + + """Emscripten's wasm-ld.""" + + def __init__(self, *args, **kwargs): + super().__init__('ld.wasm', *args, **kwargs) + + def thread_link_flags(self, env: 'Environment') -> T.List[str]: + args = ['-s', 'USE_PTHREADS=1'] + count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int + if count: + args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)]) + return args + + def get_allow_undefined_args(self) -> T.List[str]: + return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=0'] + + def no_undefined_args(self) -> T.List[str]: + return ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] + + def get_soname_args(self, env: 'Environment', prefix: str, shlib_name: str, + suffix: str, soversion: str, darwin_versions: T.Tuple[str, str], + is_shared_module: bool) -> T.List[str]: + raise mesonlib.MesonException('{} does not support shared libraries.'.format(self.id)) + + def get_asneeded_args(self) -> T.List[str]: + return [] + + class CcrxDynamicLinker(DynamicLinker): """Linker for Renesis CCrx compiler.""" -- cgit v1.2.3