blob: d2a02b7cd494084ac8fb4574413b93413d0439bf [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2015 WebAssembly Community Group participants
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import argparse
import fnmatch
import glob
import os
import os.path
import sys
import testing
# For debugging purposes set this to a source file name to test just a single
# file.
test_filter = None
def do_compile(infile, outfile, extras):
"""Create the command-line for a C compiler invocation."""
# its not enough to check only for capital `.C` extension because
# windows.
if os.path.splitext(infile)[1] == '.C' or 'g++.dg' in infile:
return [extras['cxx'], infile, '-o', outfile] + extras['cxxflags']
else:
return [extras['cc'], infile, '-o', outfile] + extras['cflags']
def create_outname(outdir, infile, extras):
if os.path.splitext(infile)[1] == '.C':
parts = infile.split(os.path.sep)
parts = parts[parts.index('testsuite') + 2:]
basename = '__'.join(parts)
else:
basename = os.path.basename(infile)
rtn = os.path.join(outdir, basename + extras['suffix'])
if os.path.exists(rtn):
raise Exception("already exists: " + rtn)
return rtn
def find_runnable_tests(directory, pattern):
results = []
for root, dirs, files in os.walk(directory):
if os.path.basename(root) == 'ext':
continue
for filename in files:
if fnmatch.fnmatch(filename, pattern):
fullname = os.path.join(root, filename)
with open(fullname, 'rb') as f:
header = f.read(1024)
# Some of these files really do have non-utf8 in them.
# TODO: open in text mode with the encoding kwarg when we
# drop py2.
header = header.decode('ISO8859-1')
if ('{ dg-do run }' in header and
'dg-additional-sources' not in header):
results.append(fullname)
return results
def run(cc, cxx, testsuite, sysroot_dir, fails, exclusions, out, config, opt):
"""Compile all torture tests."""
script_dir = os.path.dirname(os.path.abspath(__file__))
pre_js = os.path.join(script_dir, 'em_pre.js')
cflags_common = [
'-DSTACK_SIZE=524288',
'-D_WASI_EMULATED_MMAN',
'-D_WASI_EMULATED_SIGNAL',
'-w', '-Wno-implicit-function-declaration', '-' + opt
]
cflags_c = ['--std=gnu89']
cflags_cxx = []
cflags_extra = {
'clang': ['-c', '--sysroot=%s' % sysroot_dir],
'emscripten': ['--pre-js', pre_js],
}
suffix = {
'clang': '.o',
'emscripten': '.js',
}[config]
assert os.path.isdir(out), 'Cannot find outdir %s' % out
assert os.path.isfile(cc), 'Cannot find C compiler at %s' % cc
assert os.path.isfile(cxx), 'Cannot find C++ compiler at %s' % cxx
assert os.path.isdir(testsuite), 'Cannot find testsuite at %s' % testsuite
# Currently we build the following parts of the gcc test suite:
# - testsuite/gcc.c-torture/execute/*.c
# - testsuite/g++.dg (all executable tests)
# TODO(sbc) Also more parts of the test suite
c_torture = os.path.join(testsuite, 'gcc.c-torture', 'execute')
assert os.path.isdir(c_torture), ('Cannot find C tests at %s' % c_torture)
test_files = glob.glob(os.path.join(c_torture, '*.c'))
if config == 'clang':
# Only build the C++ tests when linking with lld
cxx_test_dir = os.path.join(testsuite, 'g++.dg')
assert os.path.isdir(cxx_test_dir), ('Cannot find C++ tests at %s' %
cxx_test_dir)
test_files += find_runnable_tests(cxx_test_dir, '*.[Cc]')
cflags = cflags_common + cflags_c + cflags_extra[config]
cxxflags = cflags_common + cflags_cxx + cflags_extra[config]
if test_filter:
test_files = fnmatch.filter(test_files, test_filter)
result = testing.execute(tester=testing.Tester(command_ctor=do_compile,
outname_ctor=create_outname,
outdir=out,
extras={
'cc': cc,
'cxx': cxx,
'cflags': cflags,
'cxxflags': cxxflags,
'suffix': suffix
}),
inputs=test_files,
fails=fails,
exclusions=exclusions,
attributes=[config, opt])
return result
def main():
parser = argparse.ArgumentParser(description='Compile GCC torture tests.')
parser.add_argument('--cc', type=str, required=True,
help='C compiler path')
parser.add_argument('--cxx', type=str, required=True,
help='C++ compiler path')
parser.add_argument('--testsuite', type=str, required=True,
help='GCC testsuite tests path')
parser.add_argument('--sysroot', type=str, required=True,
help='Sysroot directory')
parser.add_argument('--fails', type=str, required=True,
help='Expected failures')
parser.add_argument('--out', type=str, required=True,
help='Output directory')
parser.add_argument('--config', type=str, required=True,
help='configuration to use')
args = parser.parse_args()
return run(cc=args.cc,
cxx=args.cxx,
testsuite=args.testsuite,
sysroot_dir=args.sysroot,
fails=args.fails,
out=args.out,
config=args.config)
if __name__ == '__main__':
sys.exit(main())