run-wasm-api-tests.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2019 the V8 project authors. All rights reserved.
  4. # Use of this source code is governed by a BSD-style license that can be
  5. # found in the LICENSE file.
  6. """\
  7. Helper script for compiling and running the Wasm C/C++ API examples.
  8. Usage: tools/run-wasm-api-tests.py outdir tempdir [filters...]
  9. "outdir" is the build output directory containing libwee8, e.g. out/x64.release
  10. "tempdir" is a temporary dir where this script may put its artifacts. It is
  11. the caller's responsibility to clean it up afterwards.
  12. By default, this script builds and runs all examples, both the respective
  13. C and C++ versions, both with GCC ("gcc" and "g++" binaries found in $PATH)
  14. and V8's bundled Clang in third_party/llvm-build/. You can use any number
  15. of "filters" arguments to run only a subset:
  16. - "c": run C versions of examples
  17. - "cc": run C++ versions of examples
  18. - "gcc": compile with GCC
  19. - "clang": compile with Clang
  20. - "hello" etc.: run "hello" example
  21. """
  22. from __future__ import print_function
  23. import os
  24. import shutil
  25. import subprocess
  26. import sys
  27. CFLAGS = "-DDEBUG -Wall -Werror -O0 -ggdb -fsanitize=address"
  28. CHECKOUT_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  29. WASM_PATH = os.path.join(CHECKOUT_PATH, "third_party", "wasm-api")
  30. CLANG_PATH = os.path.join(CHECKOUT_PATH, "third_party", "llvm-build",
  31. "Release+Asserts", "bin")
  32. EXAMPLES = ["hello", "callback", "trap", "reflect", "global", "table",
  33. "memory", "finalize", "serialize", "threads", "hostref", "multi",
  34. "start"]
  35. CLANG = {
  36. "name": "Clang",
  37. "c": os.path.join(CLANG_PATH, "clang"),
  38. "cc": os.path.join(CLANG_PATH, "clang++"),
  39. "ldflags": "-fsanitize-memory-track-origins -fsanitize-memory-use-after-dtor",
  40. }
  41. GCC = {
  42. "name": "GCC",
  43. "c": "gcc",
  44. "cc": "g++",
  45. "ldflags": "",
  46. }
  47. C = {
  48. "name": "C",
  49. "suffix": "c",
  50. "cflags": "",
  51. }
  52. CXX = {
  53. "name": "C++",
  54. "suffix": "cc",
  55. "cflags": "-std=c++11",
  56. }
  57. MIN_ARGS = 3 # Script, outdir, tempdir
  58. def _Call(cmd_list, silent=False):
  59. cmd = " ".join(cmd_list)
  60. if not silent: print("# %s" % cmd)
  61. return subprocess.call(cmd, shell=True)
  62. class Runner(object):
  63. def __init__(self, name, outdir, tempdir):
  64. self.name = name
  65. self.outdir = outdir
  66. self.tempdir = tempdir
  67. self.src_file_basename = os.path.join(WASM_PATH, "example", name)
  68. self.dst_file_basename = os.path.join(tempdir, name)
  69. self.lib_file = os.path.join(outdir, "obj", "libwee8.a")
  70. if not os.path.exists(self.lib_file):
  71. print("libwee8 library not found, make sure to pass the outdir as "
  72. "first argument; see --help")
  73. sys.exit(1)
  74. src_wasm_file = self.src_file_basename + ".wasm"
  75. dst_wasm_file = self.dst_file_basename + ".wasm"
  76. shutil.copyfile(src_wasm_file, dst_wasm_file)
  77. def _Error(self, step, lang, compiler, code):
  78. print("Error: %s failed. To repro: tools/run-wasm-api-tests.py "
  79. "%s %s %s %s %s" %
  80. (step, self.outdir, self.tempdir, self.name, lang,
  81. compiler["name"].lower()))
  82. return code
  83. def CompileAndRun(self, compiler, language):
  84. print("==== %s %s/%s ====" %
  85. (self.name, language["name"], compiler["name"]))
  86. lang = language["suffix"]
  87. src_file = self.src_file_basename + "." + lang
  88. exe_file = self.dst_file_basename + "-" + lang
  89. obj_file = exe_file + ".o"
  90. # Compile.
  91. c = _Call([compiler[lang], "-c", language["cflags"], CFLAGS,
  92. "-I", WASM_PATH, "-o", obj_file, src_file])
  93. if c: return self._Error("compilation", lang, compiler, c)
  94. # Link.
  95. c = _Call([compiler["cc"], CFLAGS, compiler["ldflags"], obj_file,
  96. "-o", exe_file, self.lib_file, "-ldl -pthread"])
  97. if c: return self._Error("linking", lang, compiler, c)
  98. # Execute.
  99. exe_file = "./%s-%s" % (self.name, lang)
  100. c = _Call(["cd", self.tempdir, ";", exe_file])
  101. if c: return self._Error("execution", lang, compiler, c)
  102. return 0
  103. def Main(args):
  104. if (len(args) < MIN_ARGS or args[1] in ("-h", "--help", "help")):
  105. print(__doc__)
  106. return 1
  107. outdir = sys.argv[1]
  108. tempdir = sys.argv[2]
  109. result = 0
  110. examples = EXAMPLES
  111. compilers = (GCC, CLANG)
  112. languages = (C, CXX)
  113. if len(args) > MIN_ARGS:
  114. custom_compilers = []
  115. custom_languages = []
  116. custom_examples = []
  117. for i in range(MIN_ARGS, len(args)):
  118. arg = args[i]
  119. if arg == "c" and C not in custom_languages:
  120. custom_languages.append(C)
  121. elif arg in ("cc", "cpp", "cxx", "c++") and CXX not in custom_languages:
  122. custom_languages.append(CXX)
  123. elif arg in ("gcc", "g++") and GCC not in custom_compilers:
  124. custom_compilers.append(GCC)
  125. elif arg in ("clang", "clang++") and CLANG not in custom_compilers:
  126. custom_compilers.append(CLANG)
  127. elif arg in EXAMPLES and arg not in custom_examples:
  128. custom_examples.append(arg)
  129. else:
  130. print("Didn't understand '%s'" % arg)
  131. return 1
  132. if custom_compilers:
  133. compilers = custom_compilers
  134. if custom_languages:
  135. languages = custom_languages
  136. if custom_examples:
  137. examples = custom_examples
  138. for example in examples:
  139. runner = Runner(example, outdir, tempdir)
  140. for compiler in compilers:
  141. for language in languages:
  142. c = runner.CompileAndRun(compiler, language)
  143. if c: result = c
  144. if result:
  145. print("\nFinished with errors.")
  146. else:
  147. print("\nFinished successfully.")
  148. return result
  149. if __name__ == "__main__":
  150. sys.exit(Main(sys.argv))