Skip to content

Commit 0ade3f2

Browse files
authored
Add mozjs, V8 and WABT setup script (#3053)
Adds a new script `./third_party/setup.py` to conveniently install necessary dependencies for testing and fuzzing, including the SpiderMonkey JS shell (mozjs), the V8 JS shell and WABT. Other scripts now automatically pick these up when installed and fall back to look for the tools in PATH like before.
1 parent cd9bd14 commit 0ade3f2

File tree

10 files changed

+730
-1
lines changed

10 files changed

+730
-1
lines changed

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,24 @@ The `check.py` script supports some options:
342342
* We have tests from upstream in `tests/spec`, in git submodules. Running
343343
`./check.py` should update those.
344344

345+
### Setting up dependencies
346+
347+
```
348+
./third_party/setup.py [mozjs|v8|wabt|all]
349+
```
350+
351+
(or `python third_party/setup.py`) installs required dependencies like the SpiderMonkey JS shell, the V8 JS shell
352+
and WABT in `third_party/`. Other scripts automatically pick these up when installed.
353+
354+
### Fuzzing
355+
356+
```
357+
./scripts/fuzz_opt.py [--binaryen-bin=build/bin]
358+
```
359+
360+
(or `python scripts/fuzz_opt.py`) will run various fuzzing modes on random inputs with random passes until it finds
361+
a possible bug. See [the wiki page](https://github.com/WebAssembly/binaryen/wiki/Fuzzing) for all the details.
362+
345363
## Design Principles
346364

347365
* **Interned strings for names**: It's very convenient to have names on nodes,

scripts/test/shared.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,13 @@ def is_exe(fpath):
155155
if is_exe(program):
156156
return program
157157
else:
158-
for path in os.environ["PATH"].split(os.pathsep):
158+
paths = [
159+
# Prefer tools installed using third_party/setup.py
160+
os.path.join(options.binaryen_root, 'third_party', 'mozjs'),
161+
os.path.join(options.binaryen_root, 'third_party', 'v8'),
162+
os.path.join(options.binaryen_root, 'third_party', 'wabt', 'bin')
163+
] + os.environ['PATH'].split(os.pathsep)
164+
for path in paths:
159165
path = path.strip('"')
160166
exe_file = os.path.join(path, program)
161167
if is_exe(exe_file):

third_party/mozjs/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

third_party/setup.py

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright 2020 WebAssembly Community Group participants
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import collections
18+
import json
19+
import io
20+
import os
21+
import re
22+
import sys
23+
import tarfile
24+
import urllib.request
25+
import zipfile
26+
27+
28+
def fetch_json(url):
29+
with urllib.request.urlopen(url) as res:
30+
return json.loads(res.read().decode())
31+
32+
33+
def download_zip(url, dir):
34+
with urllib.request.urlopen(url) as res:
35+
data = io.BytesIO(res.read())
36+
archive = zipfile.ZipFile(data)
37+
for name in archive.namelist():
38+
file = archive.open(name)
39+
with open(os.path.join(dir, name), 'wb') as output:
40+
output.write(file.read())
41+
42+
43+
def download_tar(url, dir):
44+
tempfile = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'temp.tar.gz')
45+
with urllib.request.urlopen(url) as res:
46+
with open(tempfile, 'wb') as temp:
47+
temp.write(res.read())
48+
with tarfile.open(tempfile, 'r') as archive:
49+
for member in archive.getmembers():
50+
match = re.match('^[^/]+/', member.name)
51+
if match:
52+
outname = os.path.join(dir, member.name[match.span(0)[1]:])
53+
if member.isdir():
54+
if not os.path.exists(outname):
55+
os.mkdir(outname)
56+
elif member.isfile():
57+
with archive.extractfile(member) as infile:
58+
with open(outname, 'wb') as outfile:
59+
outfile.write(infile.read())
60+
if sys.platform != 'win32':
61+
os.chmod(outname, member.mode)
62+
os.remove(tempfile)
63+
64+
65+
# mozjs
66+
# see: https://github.com/GoogleChromeLabs/jsvu/tree/main/engines/spidermonkey
67+
68+
mozjs_bin = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'mozjs')
69+
70+
71+
def mozjs_determine_platform():
72+
is_64bits = sys.maxsize > 2**32
73+
if sys.platform.startswith('linux'):
74+
return 'linux-x86_64' if is_64bits else 'linux-i686'
75+
if sys.platform == 'darwin':
76+
return 'mac'
77+
if sys.platform == 'win32':
78+
return 'win64' if is_64bits else 'win32'
79+
print('Cannot determine platform, assuming \'linux-x86_64\'')
80+
return 'linux-x86_64'
81+
82+
83+
def mozjs_determine_version(platform):
84+
data = fetch_json('https://product-details.mozilla.org/1.0/firefox_history_development_releases.json')
85+
latest = ''
86+
version = ''
87+
for v, t in data.items():
88+
if t > latest:
89+
latest = t
90+
version = v
91+
return version
92+
93+
94+
def mozjs_download(platform, version):
95+
download_zip('https://archive.mozilla.org/pub/firefox/releases/' + version + '/jsshell/jsshell-' + platform + '.zip', mozjs_bin)
96+
if sys.platform != 'win32':
97+
os.rename(os.path.join(mozjs_bin, 'js'), os.path.join(mozjs_bin, 'mozjs'))
98+
os.chmod(os.path.join(mozjs_bin, 'mozjs'), 0o755)
99+
else:
100+
os.rename(os.path.join(mozjs_bin, 'js.exe'), os.path.join(mozjs_bin, 'mozjs.exe'))
101+
102+
103+
def mozjs_is_installed():
104+
return os.path.exists(os.path.join(mozjs_bin, 'mozjs.exe' if sys.platform == 'win32' else 'mozjs'))
105+
106+
107+
def mozjs_main():
108+
print('Setting up mozjs ...')
109+
platform = mozjs_determine_platform()
110+
print('* Platform: ' + platform)
111+
version = mozjs_determine_version(platform)
112+
print('* Latest version: ' + version)
113+
print('* Downloading to: ' + mozjs_bin)
114+
mozjs_download(platform, version)
115+
if mozjs_is_installed():
116+
print('* Complete')
117+
else:
118+
print('* Something went wrong :(')
119+
120+
121+
# V8
122+
# see: https://github.com/GoogleChromeLabs/jsvu/tree/main/engines/v8
123+
124+
v8_bin = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'v8')
125+
126+
127+
def v8_determine_platform():
128+
is_64bits = sys.maxsize > 2**32
129+
if sys.platform.startswith('linux'):
130+
return 'linux64' if is_64bits else 'linux32'
131+
if sys.platform == 'darwin':
132+
return 'mac64'
133+
if sys.platform == 'win32':
134+
return 'win64' if is_64bits else 'win32'
135+
print('Cannot determine platform, assuming \'linux64\'')
136+
return 'linux64'
137+
138+
139+
def v8_determine_version(platform):
140+
data = fetch_json('https://storage.googleapis.com/chromium-v8/official/canary/v8-' + platform + '-rel-latest.json')
141+
return data['version']
142+
143+
144+
def v8_download(platform, version):
145+
download_zip('https://storage.googleapis.com/chromium-v8/official/canary/v8-' + platform + '-rel-' + version + '.zip', v8_bin)
146+
if sys.platform != 'win32':
147+
os.chmod(os.path.join(v8_bin, 'd8'), 0o755)
148+
149+
150+
def v8_is_installed():
151+
return os.path.exists(os.path.join(v8_bin, 'd8.exe' if sys.platform == 'win32' else 'd8'))
152+
153+
154+
def v8_main():
155+
print('Setting up V8 ...')
156+
platform = v8_determine_platform()
157+
print('* Platform: ' + platform)
158+
version = v8_determine_version(platform)
159+
print('* Latest version: ' + version)
160+
print('* Downloading to: ' + v8_bin)
161+
v8_download(platform, version)
162+
if v8_is_installed():
163+
print('* Complete')
164+
else:
165+
print('* Something went wrong :(')
166+
167+
168+
# WABT
169+
# see: https://github.com/WebAssembly/wabt/releases
170+
171+
wabt_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'wabt')
172+
wabt_bin = os.path.join(wabt_dir, 'bin')
173+
174+
175+
def wabt_determine_platform():
176+
if sys.platform.startswith('linux'):
177+
return 'ubuntu'
178+
if sys.platform == 'darwin':
179+
return 'macos'
180+
if sys.platform == 'win32':
181+
return 'windows'
182+
print('Cannot determine platform, assuming \'ubuntu\'')
183+
return 'ubuntu'
184+
185+
186+
def wabt_determine_release(platform):
187+
data = fetch_json('https://api.github.com/repos/WebAssembly/wabt/releases/latest')
188+
for asset in data['assets']:
189+
if asset['name'].endswith('-' + platform + '.tar.gz'):
190+
return asset['browser_download_url']
191+
print('Cannot determine release')
192+
return ''
193+
194+
195+
def wabt_download(release):
196+
download_tar(release, wabt_dir)
197+
198+
199+
def wabt_is_installed():
200+
return os.path.exists(os.path.join(wabt_bin, 'wasm2c.exe' if sys.platform == 'win32' else 'wasm2c'))
201+
202+
203+
def wabt_main():
204+
print('Setting up WABT ...')
205+
platform = wabt_determine_platform()
206+
print('* Platform: ' + platform)
207+
release = wabt_determine_release(platform)
208+
print('* Latest release: ' + release)
209+
print('* Downloading to: ' + wabt_bin)
210+
wabt_download(release)
211+
if wabt_is_installed():
212+
print('* Complete')
213+
else:
214+
print('* Something went wrong :(')
215+
216+
217+
TOOLS = collections.OrderedDict([
218+
('mozjs', mozjs_main),
219+
('v8', v8_main),
220+
('wabt', wabt_main),
221+
])
222+
223+
if __name__ == '__main__':
224+
if len(sys.argv) < 2 or sys.argv[1] == '--help':
225+
msg = ''
226+
for key in TOOLS.keys():
227+
if len(msg):
228+
msg += '|'
229+
msg += key
230+
print('usage: ./setup.py [' + msg + '|all]')
231+
sys.exit(0)
232+
tool = sys.argv[1]
233+
if tool == 'all':
234+
for main in TOOLS.values():
235+
code = main()
236+
if code:
237+
sys.exit(code)
238+
sys.exit(0)
239+
elif TOOLS[tool]:
240+
main = TOOLS[tool]
241+
sys.exit(main())
242+
else:
243+
print('No such tool: ' + tool)
244+
sys.exit(1)

third_party/v8/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

third_party/wabt/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
*
2+
!.gitignore
3+
!wasm2c
4+
!wasm2c/*

third_party/wabt/wasm2c/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
These files are part of WABT, but are currently not present in releases, so the
2+
directory is included as a fallback in Binaryen in a way that the files will be
3+
overwritten in case WABT contains them in the future.
4+
5+
Original README: https://github.com/WebAssembly/wabt/blob/master/wasm2c/README.md

0 commit comments

Comments
 (0)