summaryrefslogtreecommitdiff
path: root/deps/v8/tools/run-wasm-api-tests.py
blob: 46e13d3255cbe41fd96504a11d30d0c7c1402bd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#!/usr/bin/env python
#
# Copyright 2019 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""\
Helper script for compiling and running the Wasm C/C++ API examples.

Usage: tools/run-wasm-api-tests.py outdir tempdir [filters...]

"outdir" is the build output directory containing libwee8, e.g. out/x64.release
"tempdir" is a temporary dir where this script may put its artifacts. It is
the caller's responsibility to clean it up afterwards.

By default, this script builds and runs all examples, both the respective
C and C++ versions, both with GCC ("gcc" and "g++" binaries found in $PATH)
and V8's bundled Clang in third_party/llvm-build/. You can use any number
of "filters" arguments to run only a subset:
 - "c": run C versions of examples
 - "cc": run C++ versions of examples
 - "gcc": compile with GCC
 - "clang": compile with Clang
 - "hello" etc.: run "hello" example
"""

from __future__ import print_function

import os
import shutil
import subprocess
import sys

CFLAGS = "-DDEBUG -Wall -Werror -O0 -fsanitize=address"

CHECKOUT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
WASM_PATH = os.path.join(CHECKOUT_PATH, "third_party", "wasm-api")
CLANG_PATH = os.path.join(CHECKOUT_PATH, "third_party", "llvm-build",
                          "Release+Asserts", "bin")

EXAMPLES = ["hello", "callback", "trap", "reflect", "global", "table",
            "memory", "finalize", "serialize", "threads"]

CLANG = {
  "name": "Clang",
  "c": os.path.join(CLANG_PATH, "clang"),
  "cc": os.path.join(CLANG_PATH, "clang++"),
  "ldflags": "-fsanitize-memory-track-origins -fsanitize-memory-use-after-dtor",
}
GCC = {
  "name": "GCC",
  "c": "gcc",
  "cc": "g++",
  "ldflags": "",
}

C = {
  "name": "C",
  "suffix": "c",
  "cflags": "",
}
CXX = {
  "name": "C++",
  "suffix": "cc",
  "cflags": "-std=c++11",
}

MIN_ARGS = 3  # Script, outdir, tempdir

def _Call(cmd_list, silent=False):
  cmd = " ".join(cmd_list)
  if not silent: print("# %s" % cmd)
  return subprocess.call(cmd, shell=True)

class Runner(object):
  def __init__(self, name, outdir, tempdir):
    self.name = name
    self.outdir = outdir
    self.tempdir = tempdir
    self.src_file_basename = os.path.join(WASM_PATH, "example", name)
    self.dst_file_basename = os.path.join(tempdir, name)
    self.lib_file = os.path.join(outdir, "obj", "libwee8.a")
    if not os.path.exists(self.lib_file):
      print("libwee8 library not found, make sure to pass the outdir as "
            "first argument; see --help")
      sys.exit(1)
    src_wasm_file = self.src_file_basename + ".wasm"
    dst_wasm_file = self.dst_file_basename + ".wasm"
    shutil.copyfile(src_wasm_file, dst_wasm_file)

  def _Error(self, step, lang, compiler):
    print("Error: %s failed. To repro: tools/run-wasm-api-tests.py "
          "%s %s %s %s %s" %
          (step, self.outdir, self.tempdir, self.name, lang,
           compiler["name"].lower()))


  def CompileAndRun(self, compiler, language):
    print("==== %s %s/%s ====" %
          (self.name, language["name"], compiler["name"]))
    lang = language["suffix"]
    src_file = self.src_file_basename + "." + lang
    exe_file = self.dst_file_basename + "-" + lang
    obj_file = exe_file  + ".o"
    # Compile.
    c = _Call([compiler[lang], "-c", language["cflags"], CFLAGS,
               "-I", WASM_PATH, "-o", obj_file, src_file])
    if c: return self._Error("compilation", lang, compiler)
    # Link.
    c = _Call([compiler["cc"], CFLAGS, compiler["ldflags"], obj_file,
               "-o", exe_file, self.lib_file, "-ldl -pthread"])
    if c: return self._Error("linking", lang, compiler)
    # Execute.
    exe_file = "./%s-%s" % (self.name, lang)
    c = _Call(["cd", self.tempdir, ";", exe_file])
    if c: return self._Error("execution", lang, compiler)
    return 0

def Main(args):
  if (len(args) < MIN_ARGS or args[1] in ("-h", "--help", "help")):
    print(__doc__)
    return 1

  outdir = sys.argv[1]
  tempdir = sys.argv[2]
  result = 0
  examples = EXAMPLES
  compilers = (GCC, CLANG)
  languages = (C, CXX)
  if len(args) > MIN_ARGS:
    custom_compilers = []
    custom_languages = []
    custom_examples = []
    for i in range(MIN_ARGS, len(args)):
      arg = args[i]
      if arg == "c" and C not in custom_languages:
        custom_languages.append(C)
      elif arg in ("cc", "cpp", "cxx", "c++") and CXX not in custom_languages:
        custom_languages.append(CXX)
      elif arg in ("gcc", "g++") and GCC not in custom_compilers:
        custom_compilers.append(GCC)
      elif arg in ("clang", "clang++") and CLANG not in custom_compilers:
        custom_compilers.append(CLANG)
      elif arg in EXAMPLES and arg not in custom_examples:
        custom_examples.append(arg)
      else:
        print("Didn't understand '%s'" % arg)
        return 1
    if custom_compilers:
      compilers = custom_compilers
    if custom_languages:
      languages = custom_languages
    if custom_examples:
      examples = custom_examples
  for example in examples:
    runner = Runner(example, outdir, tempdir)
    for compiler in compilers:
      for language in languages:
        c = runner.CompileAndRun(compiler, language)
        if c: result = c
  return result

if __name__ == "__main__":
  sys.exit(Main(sys.argv))