aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2020-03-08 14:04:48 +0200
committerGitHub <noreply@github.com>2020-03-08 14:04:48 +0200
commit7234316dc7784667443d358b0d2c3e2ff561b474 (patch)
treefbf0413aaa221acd2a8437b75cf5dd349471563c
parenta16db4e9185fcf060ea3e336cbffbe16018be934 (diff)
parent654f427759d5aa3be55d8929b18c17a2b8fcac69 (diff)
downloadmeson-7234316dc7784667443d358b0d2c3e2ff561b474.zip
meson-7234316dc7784667443d358b0d2c3e2ff561b474.tar.gz
meson-7234316dc7784667443d358b0d2c3e2ff561b474.tar.bz2
Merge pull request #6688 from dcbaker/emcc-linker-bugs
Emcc linker bugs and improvments
-rw-r--r--docs/markdown/Builtin-options.md34
-rw-r--r--docs/markdown/Reference-tables.md3
-rw-r--r--docs/markdown/snippets/emscripten_threads.md6
-rw-r--r--docs/markdown/snippets/wasm_ld.md5
-rw-r--r--mesonbuild/compilers/c.py4
-rw-r--r--mesonbuild/compilers/cpp.py4
-rw-r--r--mesonbuild/compilers/mixins/emscripten.py29
-rw-r--r--mesonbuild/compilers/mixins/islinker.py9
-rw-r--r--mesonbuild/environment.py12
-rw-r--r--mesonbuild/linkers.py29
-rw-r--r--test cases/wasm/1 basic/hello.c7
-rw-r--r--test cases/wasm/1 basic/meson.build3
-rw-r--r--test cases/wasm/2 threads/meson.build10
-rw-r--r--test cases/wasm/2 threads/threads.c21
-rw-r--r--test cases/wasm/2 threads/threads.cpp13
15 files changed, 157 insertions, 32 deletions
diff --git a/docs/markdown/Builtin-options.md b/docs/markdown/Builtin-options.md
index 9c8c54c..c2b10b6 100644
--- a/docs/markdown/Builtin-options.md
+++ b/docs/markdown/Builtin-options.md
@@ -151,20 +151,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, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, <br/> 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, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, <br/> 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,
@@ -179,3 +181,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 `<lang>_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/Reference-tables.md b/docs/markdown/Reference-tables.md
index 9f432f0..59e252f 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/emscripten_threads.md b/docs/markdown/snippets/emscripten_threads.md
new file mode 100644
index 0000000..bdf808e
--- /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<lang>_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/docs/markdown/snippets/wasm_ld.md b/docs/markdown/snippets/wasm_ld.md
new file mode 100644
index 0000000..d47767c
--- /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 a9ad585..f98316b 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,
@@ -139,7 +139,7 @@ class AppleClangCCompiler(ClangCCompiler):
_C18_VERSION = '>=11.0.0'
-class EmscriptenCCompiler(LinkerEnvVarsMixin, EmscriptenMixin, BasicLinkerIsCompilerMixin, 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 26b34e3..2470bd5 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:
@@ -207,7 +207,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler):
pass
-class EmscriptenCPPCompiler(LinkerEnvVarsMixin, EmscriptenMixin, BasicLinkerIsCompilerMixin, 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 945a67d..10f4b25 100644
--- a/mesonbuild/compilers/mixins/emscripten.py
+++ b/mesonbuild/compilers/mixins/emscripten.py
@@ -17,20 +17,13 @@
import os.path
import typing as T
-from ...mesonlib import MesonException
+from ... import coredata
-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.')
+if T.TYPE_CHECKING:
+ from ..environment import Environment
- 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]
+class EmscriptenMixin:
def _get_compile_output(self, dirname, mode):
# In pre-processor mode, the output is sent to stdout and discarded
@@ -44,3 +37,17 @@ 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 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/mesonbuild/compilers/mixins/islinker.py b/mesonbuild/compilers/mixins/islinker.py
index 4e0af88..3092395 100644
--- a/mesonbuild/compilers/mixins/islinker.py
+++ b/mesonbuild/compilers/mixins/islinker.py
@@ -130,3 +130,12 @@ class BasicLinkerIsCompilerMixin:
def get_buildtype_linker_args(self, buildtype: str) -> T.List[str]:
return []
+
+ def get_link_debugfile_name(self, target: str) -> str:
+ return ''
+
+ def thread_flags(self, env: 'Environment') -> T.List[str]:
+ return []
+
+ def thread_link_flags(self, env: 'Environment') -> T.List[str]:
+ return []
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
index 5e60294..7fda3be 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 (
@@ -963,9 +964,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 489525b..73cdeef 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."""
diff --git a/test cases/wasm/1 basic/hello.c b/test cases/wasm/1 basic/hello.c
new file mode 100644
index 0000000..a104b37
--- /dev/null
+++ b/test cases/wasm/1 basic/hello.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+int main() {
+ printf("Hello World\n");
+ return 0;
+}
+
diff --git a/test cases/wasm/1 basic/meson.build b/test cases/wasm/1 basic/meson.build
index 8fe713c..1092a9b 100644
--- a/test cases/wasm/1 basic/meson.build
+++ b/test cases/wasm/1 basic/meson.build
@@ -1,3 +1,4 @@
-project('emcctest', 'cpp')
+project('emcctest', 'c', 'cpp')
+executable('hello-c', 'hello.c')
executable('hello', 'hello.cpp')
diff --git a/test cases/wasm/2 threads/meson.build b/test cases/wasm/2 threads/meson.build
new file mode 100644
index 0000000..cb682b8
--- /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 0000000..e79bff1
--- /dev/null
+++ b/test cases/wasm/2 threads/threads.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+
+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 0000000..1caa73d
--- /dev/null
+++ b/test cases/wasm/2 threads/threads.cpp
@@ -0,0 +1,13 @@
+#include <unistd.h>
+#include <iostream>
+#include <thread>
+
+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;
+}