From b6ccfe218b327e36918b66140d4cdab89aee3c62 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 14:10:40 -0700 Subject: [PATCH 01/13] Add support for Rust test cases. --- .travis.yml | 2 ++ mx.sulong/mx_buildtools.py | 30 +++++++++++++++++ mx.sulong/mx_sulong.py | 33 +++++++++++++++++-- mx.sulong/mx_testsuites.py | 13 +++++++- mx.sulong/suite.py | 9 +++++ rust-toolchain | 1 + tests/Makefile | 16 ++++++++- .../rust/test001.rs | 3 ++ .../rust/test002.rs | 3 ++ 9 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 rust-toolchain create mode 100644 tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs create mode 100644 tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs diff --git a/.travis.yml b/.travis.yml index c532522c4..6fcafc2fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ cache: dist: trusty sudo: required language: generic +language: rust + - 1.19.0 install: - cd .. - gem install mdl diff --git a/mx.sulong/mx_buildtools.py b/mx.sulong/mx_buildtools.py index 36e5ff9eb..124d0a202 100644 --- a/mx.sulong/mx_buildtools.py +++ b/mx.sulong/mx_buildtools.py @@ -64,6 +64,7 @@ def lookupFile(f): ProgrammingLanguage.register('C', 'c') ProgrammingLanguage.register('C_PLUS_PLUS', 'cpp', 'cc', 'C') ProgrammingLanguage.register('OBJECTIVE_C', 'm') +ProgrammingLanguage.register('RUST', 'rs') ProgrammingLanguage.register('LLVMIR', 'll') ProgrammingLanguage.register('LLVMBC', 'bc') ProgrammingLanguage.register('LLVMSU', 'su') @@ -192,6 +193,33 @@ def compileReferenceFile(self, inputFile, outputFile, flags): tool, toolFlags = self.getTool(inputFile, outputFile) return self.runTool([tool, '-o', outputFile] + toolFlags + flags + [inputFile], errorMsg='Cannot compile %s with %s' % (inputFile, tool)) +class RustCompiler(Tool): + def __init__(self, name=None, supportedLanguages=None): + if name is None: + self.name = 'rustc' + else: + self.name = name + + if supportedLanguages is None: + self.supportedLanguages = [ProgrammingLanguage.RUST] + else: + self.supportedLanguages = supportedLanguages + + def getTool(self, inputFile): + inputLanguage = ProgrammingLanguage.lookupFile(inputFile) + if inputLanguage == ProgrammingLanguage.RUST: + return 'rustc' + else: + raise Exception('Unsupported input language') + + def run(self, inputFile, outputFile, flags): + tool = self.getTool(inputFile) + return self.runTool([tool, '--emit=llvm-bc', '-o', outputFile] + flags + [inputFile], errorMsg='Cannot compile %s with %s' % (inputFile, tool)) + + def compileReferenceFile(self, inputFile, outputFile, flags): + tool = self.getTool(inputFile) + return self.runTool([tool, '-o', outputFile] + flags + [inputFile], errorMsg='Cannot compile %s with %s' % (inputFile, tool)) + class Opt(Tool): def __init__(self, name, passes): self.name = name @@ -208,6 +236,8 @@ def run(self, inputFile, outputFile, flags): Tool.GCC = GCCCompiler() Tool.GFORTRAN = GCCCompiler('gfortran', [ProgrammingLanguage.FORTRAN]) +Tool.RUSTC = RustCompiler() + Tool.MISC_OPTS = Opt('MISC_OPTS', ['-functionattrs', '-instcombine', '-always-inline', '-jump-threading', '-simplifycfg', '-mem2reg']) Tool.MEM2REG = Opt('MEM2REG', ['-mem2reg']) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 19706cfbd..0f666ba51 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -32,6 +32,7 @@ from os.path import join import shutil import subprocess +import glob from argparse import ArgumentParser import mx @@ -84,6 +85,7 @@ basicLLVMDependencies = [ 'clang', 'clang++', + 'rustc', 'opt', 'llc', 'llvm-as' @@ -112,6 +114,9 @@ def _unittest_config_participant(config): (vmArgs, mainClass, mainClassArgs) = config libs = [mx_subst.path_substitutions.substitute('/')] + rustStd = findRustLibrary('std', on_failure=lambda msg: None) + if rustStd is not None: + libs.append(rustStd) vmArgs = getCommonOptions(True, libs) + vmArgs return (vmArgs, mainClass, mainClassArgs) @@ -284,6 +289,15 @@ def dragonEggGPP(args=None): executeCommand = [getGPP(), "-fplugin=" + dragonEggPath(), '-fplugin-arg-dragonegg-emit-ir'] return mx.run(executeCommand + args) +def checkRust(): + """checks if a Rust installation is available; tries to install the active toolchain if it is missing""" + if not which('rustc'): + return False + + rustc = subprocess.Popen(['rustc', '--version'], stdout=subprocess.PIPE) + rustc.communicate() + return rustc.returncode == 0 + def which(program, searchPath=None): def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) @@ -583,6 +597,23 @@ def findGCCProgram(gccProgram, optional=False): else: return installedProgram +def findRustLibrary(name, on_failure=exit): + """looks up the path to the given Rust library for the active toolchain; tries to install the active toolchain if it is missing; exits if installation fails""" + if not checkRust(): + on_failure('Rust is not available') + return None + + rustc = subprocess.Popen(['rustc', '--print', 'sysroot'], stdout=subprocess.PIPE) + sysroot = rustc.communicate()[0].rstrip() + lib_paths = glob.glob(os.path.join(sysroot, 'lib', mx.add_lib_suffix('lib' + name + '-*'))) + if len(lib_paths) == 0: + on_failure('could not find Rust library ' + name) + return None + else: + return lib_paths[0] + +mx_subst.path_substitutions.register_with_arg('rustlib', findRustLibrary) + def getClasspathOptions(): """gets the classpath of the Sulong distributions""" return mx.get_runtime_jvm_args(['SULONG', 'SULONG_LAUNCHER']) @@ -606,8 +637,6 @@ def opt(args=None, version=None, out=None, err=None): # Project classes -import glob - class ArchiveProject(mx.ArchivableProject): def __init__(self, suite, name, deps, workingSets, theLicense, **args): mx.ArchivableProject.__init__(self, suite, name, deps, workingSets, theLicense) diff --git a/mx.sulong/mx_testsuites.py b/mx.sulong/mx_testsuites.py index 9d7d890fd..48a6504d6 100644 --- a/mx.sulong/mx_testsuites.py +++ b/mx.sulong/mx_testsuites.py @@ -299,16 +299,27 @@ def haveDragonegg(): SulongTestSuite._haveDragonegg = mx_sulong.dragonEggPath() is not None and os.path.exists(mx_sulong.dragonEggPath()) and mx_sulong.getGCC(optional=True) is not None return SulongTestSuite._haveDragonegg + @staticmethod + def haveRust(): + if not hasattr(SulongTestSuite, '_haveRust'): + SulongTestSuite._haveRust = mx_sulong.checkRust() + return SulongTestSuite._haveRust + def getTests(self): if not hasattr(self, '_tests'): self._tests = [] + extensions = ['.c', '.cpp', '.rs'] root = os.path.join(self.dir, self.name) for path, _, files in os.walk(root): for f in files: absPath = os.path.join(path, f) relPath = os.path.relpath(absPath, root) test, ext = os.path.splitext(relPath) - if ext in ['.c', '.cpp']: + if ext in extensions: + if ext == '.rs' and not SulongTestSuite.haveRust(): + mx.warn('Rust is not available, not building Rust test files') + extensions.remove('.rs') + continue self._tests.append(test) return self._tests diff --git a/mx.sulong/suite.py b/mx.sulong/suite.py index 72252332f..61ddc12a1 100644 --- a/mx.sulong/suite.py +++ b/mx.sulong/suite.py @@ -363,6 +363,14 @@ }, "testProject" : True, }, + "com.oracle.truffle.llvm.tests.sulongrust" : { + "subDir" : "tests", + "class" : "SulongTestSuite", + "variants" : ["O0"], + "buildEnv" : { + "OS" : "", + }, + }, "com.oracle.truffle.llvm.tests.libc" : { "subDir" : "tests", "class" : "SulongTestSuite", @@ -478,6 +486,7 @@ "com.oracle.truffle.llvm.tests.sulong", "com.oracle.truffle.llvm.tests.sulongavx", "com.oracle.truffle.llvm.tests.sulongcpp", + "com.oracle.truffle.llvm.tests.sulongrust", "com.oracle.truffle.llvm.tests.libc", ], "license" : "BSD-new", diff --git a/rust-toolchain b/rust-toolchain new file mode 100644 index 000000000..815d5ca06 --- /dev/null +++ b/rust-toolchain @@ -0,0 +1 @@ +1.19.0 diff --git a/tests/Makefile b/tests/Makefile index f4d522188..441392670 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -47,10 +47,16 @@ BC_FILE= else EMBED_BC= BC_FILE=%/O0.bc.o +endif + +AR_BC_FILE=%/O0.bc.a +AR_BC_NAME=O0.bc %.bc.o: %.bc $(QUIETLY) objcopy -I binary -O elf64-x86-64 -B i386:x86-64 --rename-section .data=.llvmbc $< $@ -endif + +%.bc.a: %.bc.o + $(QUIETLY) ar rcs $(@D)/lib$(@F) $< %/ref.out: %.c $(BC_FILE) @mkdir -p $(shell dirname $@) @@ -60,6 +66,10 @@ endif @mkdir -p $(shell dirname $@) $(QUIETLY) clang++ $(EMBED_BC) -Wno-everything $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ +%/ref.out: %.rs $(AR_BC_FILE) + @mkdir -p $(shell dirname $@) + $(QUIETLY) rustc -L$(@D) -lstatic=$(AR_BC_NAME) -C link-dead-code -o $@ $< + %.bc: %.ll $(QUIETLY) $(DRAGONEGG_LLVMAS) -o $@ $< @@ -72,6 +82,10 @@ define OPT_RULES @mkdir -p $$(shell dirname $$@) $(QUIETLY) clang++ -c -emit-llvm $(2) -Wno-everything $(CPPFLAGS) $(CXXFLAGS) -g -o $$@ $$< +%/$(1).bc: %.rs + @mkdir -p $$(shell dirname $$@) + $(QUIETLY) rustc --emit=llvm-bc -o $$@ $$< + %/gcc_$(1).ll: %.c @mkdir -p $$(shell dirname $$@) $(QUIETLY) $(DRAGONEGG_GCC) -w -S --std=gnu99 -fplugin=$(DRAGONEGG) -fplugin-arg-dragonegg-emit-ir -$(1) $(CPPFLAGS) $(CFLAGS) -o $$@ $$< diff --git a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs new file mode 100644 index 000000000..b51564175 --- /dev/null +++ b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs @@ -0,0 +1,3 @@ +fn main(){ + std::process::exit(42); +} diff --git a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs new file mode 100644 index 000000000..f116527e2 --- /dev/null +++ b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs @@ -0,0 +1,3 @@ +fn main(){ + println!("Hello World!"); +} From 41f1f864b059c1f67d2b49b328a189d2d2991b03 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 15:33:54 -0700 Subject: [PATCH 02/13] Add library alias for Rust libraries. --- mx.sulong/mx_sulong.py | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 0f666ba51..e777a415c 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -448,7 +448,7 @@ def extract_compiler_args(args, useDoubleDash=False): def runLLVM(args=None, out=None): """uses Sulong to execute a LLVM IR file""" vmArgs, sulongArgs = truffle_extract_VM_args(args) - return mx.run_java(getCommonOptions(False) + vmArgs + getClasspathOptions() + ["com.oracle.truffle.llvm.launcher.LLVMLauncher"] + sulongArgs, out=out) + return mx.run_java(getCommonOptions(False) + substituteLibAliases(vmArgs) + getClasspathOptions() + ["com.oracle.truffle.llvm.launcher.LLVMLauncher"] + sulongArgs, out=out) def getCommonOptions(withAssertion, lib_args=None): options = ['-Dgraal.TruffleCompilationExceptionsArePrinted=true', @@ -464,6 +464,37 @@ def getCommonOptions(withAssertion, lib_args=None): return options +def substituteLibAliases(vmArgs): + librariesOption = '-Dpolyglot.llvm.libraries=' + substitutedVmArgs = [] + lib_args = None + for vmArg in vmArgs: + if vmArg.startswith(librariesOption): + lib_args = vmArg[len(librariesOption):].split(':') + else: + substitutedVmArgs.append(vmArg) + if lib_args is None: + return vmArgs + + lib_aliases = { + 'l(.*)rust' : '' + } + + lib_aliases = {re.compile(k+'$'):v for k, v in lib_aliases.items()} + resolved_lib_args = [] + for lib_arg in lib_args: + for lib_alias, lib_alias_value in lib_aliases.items(): + match = lib_alias.match(lib_arg) + if match: + lib_arg = lib_alias_value + if match.lastindex is not None: + lib_arg = lib_arg.replace('*', match.group(1)) + lib_arg = mx_subst.path_substitutions.substitute(lib_arg) + resolved_lib_args.append(lib_arg) + substitutedVmArgs.append(librariesOption + ':'.join(resolved_lib_args)) + + return substitutedVmArgs + def getLLVMRootOption(): return "-Dsulongtest.projectRoot=" + _root From cf48c149816877de742cb8f6a30a4d192ac8c816 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 15:34:13 -0700 Subject: [PATCH 03/13] Document Rust support. --- README.md | 16 +++++++++++++--- docs/FAQ.md | 18 ++++++++++++++++++ docs/TESTS.md | 10 ++++++++-- 3 files changed, 39 insertions(+), 5 deletions(-) mode change 100644 => 100755 README.md mode change 100644 => 100755 docs/FAQ.md mode change 100644 => 100755 docs/TESTS.md diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 65c4a5c00..f6fe88e1c --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ GraalVM by [Oracle Labs](https://labs.oracle.com). Sulong is written in Java and uses the Truffle language implementation framework and Graal as a dynamic compiler. -With Sulong you can execute C/C++, Fortran, and other programming languages +With Sulong you can execute C/C++, Fortran, Rust and other programming languages that can be transformed to LLVM bitcode on Graal VM. To execute a program, you have to compile the program to LLVM bitcode by a LLVM front end such as `clang`. @@ -63,7 +63,7 @@ through the Graal Polyglot SDK. #### Compiling to LLVM bitcode format -Graal VM can execute C/C++, Fortran, and other programs that can be compiled to +Graal VM can execute C/C++, Fortran, Rust and other programs that can be compiled to LLVM bitcode. As a first step, you have to compile the program to LLVM bitcode using an LLVM frontend such as `clang`. C/C++ code can be compiled to LLVM bitcode using `clang` with the `-emit-llvm` option. @@ -99,6 +99,11 @@ Sulong is mostly implemented in Java. However, parts of Sulong are implemented in C/C++ and will be compiled to a shared library or a bitcode file. For a successful build you need to have LLVM (incl. `CLANG` and `OPT` tool) v3.8 - v6.0 installed. +Sulong also optionally depends on a Rust installation (refer to [Install Rust](https://www.rust-lang.org/en-US/install.html)). On Linux the recommended command line looks as follows: + + curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none + +This will download the Rust toolchain installer `rustup`, which in turn will automatically install the correct Rust toolchain upon building Sulong. MacOS: Apple's default LLVM does not contain the `opt` tool, which a Sulong build needs. We recommend installing LLVM via `homebrew` and appending the @@ -115,7 +120,7 @@ bitcode files, there are no special runtime dependencies, but additional libraries might be needed if the user code has external dependencies. In particular, for running C++ code, you need libc++ (the C++ standard -library from the LLVM project). +library from the LLVM project). For running Rust code you may need to link the Rust standard library `libstd`. How to get started? ------------------- @@ -174,6 +179,11 @@ multiple arguments separated by `:`. mx lli -Dpolyglot.llvm.libraryPath=lib -Dpolyglot.llvm.libraries=liba.so test.bc +Executing Rust bitcode files may require linking the Rust standard library. Use the alias `lstdrust` to conveniently load the standard library of the currently active Rust toolchain (default: specified in the `rust-toolchain` file). Note that this may automatically install a missing Rust toolchain if the Rust version specified in the `rust-toolchain` file is unavailable: + + rustc --emit=llvm-bc test.rs + mx lli -Dpolyglot.llvm.libraries=lstdrust test.bc + If you want to use the project from within Eclipse, use the following command to generate the Eclipse project files (there is also mx ideinit for other IDEs): diff --git a/docs/FAQ.md b/docs/FAQ.md old mode 100644 new mode 100755 index 6ee52425e..32bb667b5 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -55,3 +55,21 @@ In Eclipse, set a breakpoint, navigate to of the debug configurations, e.g.,`truffle-attach-localhost-8000`. After clicking `Debug`, execution starts and the program should stop at the specified breakpoint. + +## Rust + +### How can I fix the following warning I get when building Sulong: `Rust is not available, not building Rust test files` + +Make sure that Rust is available on your system and that the `PATH` is configured to include the `.cargo/bin` directory of your Rust installation. + +### How can I override the Rust version specified in the `rust-toolchain` file? + +By default, Sulong uses the pinned Rust toolchain specified in the `rust-toolchain` file for compiling the Rust test cases and for linking the Rust standard library in the case that the library alias `lstdrust` is given. For instructions on how to override a `rust-toolchain` file, please refer to the `rustup` docs (-> [Directory overrides](https://github.com/rust-lang-nursery/rustup.rs/blob/master/README.md#directory-overrides)). + +Here is an example showing how to temporarily override the current toolchain setting: + + rustup install nightly + rustup run nightly rustc --emit=llvm-bc test.rs + rustup run nightly mx lli -Dpolyglot.llvm.libraries=lstdrust test.bc + + diff --git a/docs/TESTS.md b/docs/TESTS.md old mode 100644 new mode 100755 index eb31bd505..96bf48da6 --- a/docs/TESTS.md +++ b/docs/TESTS.md @@ -25,9 +25,9 @@ Please note that this command aborts as soon as one testsuite has failed. | callback | CallbackTest | Test calling native functions | | type | - | Test floating point arithmetic | -The test cases consist of LLVM IR, C, C++, and Fortran files. While +The test cases consist of LLVM IR, C, C++, Fortran and Rust files. While Sulong's Truffle LLVM IR interpreter can directly execute the LLVM IR -files it uses Clang and/or GCC to compile the other source files to LLVM IR +files it uses a selection from amongst the tools Clang, GCC and rustc to compile the other source files to LLVM IR before executing them. ### Testgate @@ -133,6 +133,12 @@ DYLD_LIBRARY_PATH cannot normally be set on the Mac. ln -s /usr/local/Cellar/gcc46/4.6.4/lib/gcc/4.6/libgfortran.3.dylib /usr/local/lib +## Rust + +Some of our tests are Rust files. Make sure you have a recent version of the Rust toolchain installer `rustup` available. When doing a complete rebuild of Sulong, an attempt will be made to compile the Rust test files using the rustc of the currently active toolchain (default: specified in the `rust-toolchain` file). Note that this may automatically install a missing Rust toolchain if the Rust version specified in the `rust-toolchain` file is unavailable. + +For unittests Sulong automatically links the Rust standard library of the currently active toolchain. + ## Reference output For most test cases, Sulong obtains the reference output (return value and/or From 98d39840905ea214ccd4caa54a54f774cb80b670 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 15:35:26 -0700 Subject: [PATCH 04/13] Add environment variable SULONG_USE_RUSTC. --- README.md | 2 +- mx.sulong/mx_sulong.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f6fe88e1c..728468e6b 100755 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Sulong also optionally depends on a Rust installation (refer to [Install Rust](h curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -This will download the Rust toolchain installer `rustup`, which in turn will automatically install the correct Rust toolchain upon building Sulong. +This will download the Rust toolchain installer `rustup`, which in turn will automatically install the correct Rust toolchain upon building Sulong. You can prohibit Sulong from using an available Rust installation by setting `SULONG_USE_RUSTC` to `false`. MacOS: Apple's default LLVM does not contain the `opt` tool, which a Sulong build needs. We recommend installing LLVM via `homebrew` and appending the diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index e777a415c..171e6fa06 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -291,7 +291,7 @@ def dragonEggGPP(args=None): def checkRust(): """checks if a Rust installation is available; tries to install the active toolchain if it is missing""" - if not which('rustc'): + if os.environ.get('SULONG_USE_RUSTC', 'true') == 'false' or not which('rustc'): return False rustc = subprocess.Popen(['rustc', '--version'], stdout=subprocess.PIPE) From 94d261d180240ea46a8c3ecf8d4309521c2a5a9a Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 15:37:09 -0700 Subject: [PATCH 05/13] Add libs file for recording library dependencies of unit tests. --- mx.sulong/mx_sulong.py | 37 ++++++++------ mx.sulong/mx_testsuites.py | 101 ++++++++++++++++++++++--------------- mx.sulong/suite.py | 3 ++ tests/Makefile | 8 ++- 4 files changed, 93 insertions(+), 56 deletions(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 171e6fa06..e07b320b2 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -113,11 +113,15 @@ def _unittest_config_participant(config): (vmArgs, mainClass, mainClassArgs) = config - libs = [mx_subst.path_substitutions.substitute('/')] - rustStd = findRustLibrary('std', on_failure=lambda msg: None) - if rustStd is not None: - libs.append(rustStd) - vmArgs = getCommonOptions(True, libs) + vmArgs + libs = ['/'] + (testSuitePath,), _ = extract_arg_values(vmArgs, '-Dsulongtest.testSuitePath') + + # gather library dependencies + for libs_file in glob.glob(os.path.join(testSuitePath, '*', 'libs')): + with open(libs_file, 'r') as l: + libs += l.readline().split() + + vmArgs = getCommonOptions(True, [mx_subst.path_substitutions.substitute(lib) for lib in libs]) + vmArgs return (vmArgs, mainClass, mainClassArgs) add_config_participant(_unittest_config_participant) @@ -445,6 +449,15 @@ def extract_compiler_args(args, useDoubleDash=False): remainder += [arg] return compilerArgs, remainder +def extract_arg_values(vmArgs, argKey): + values, remainder = [], [] + for arg in vmArgs: + if arg.startswith(argKey + '='): + values += arg[(len(argKey)+1):].split(':') + else: + remainder += [arg] + return values, remainder + def runLLVM(args=None, out=None): """uses Sulong to execute a LLVM IR file""" vmArgs, sulongArgs = truffle_extract_VM_args(args) @@ -465,15 +478,9 @@ def getCommonOptions(withAssertion, lib_args=None): return options def substituteLibAliases(vmArgs): - librariesOption = '-Dpolyglot.llvm.libraries=' - substitutedVmArgs = [] - lib_args = None - for vmArg in vmArgs: - if vmArg.startswith(librariesOption): - lib_args = vmArg[len(librariesOption):].split(':') - else: - substitutedVmArgs.append(vmArg) - if lib_args is None: + librariesOption = '-Dpolyglot.llvm.libraries' + lib_args, substitutedVmArgs = extract_arg_values(vmArgs, librariesOption) + if len(lib_args) == 0: return vmArgs lib_aliases = { @@ -491,7 +498,7 @@ def substituteLibAliases(vmArgs): lib_arg = lib_arg.replace('*', match.group(1)) lib_arg = mx_subst.path_substitutions.substitute(lib_arg) resolved_lib_args.append(lib_arg) - substitutedVmArgs.append(librariesOption + ':'.join(resolved_lib_args)) + substitutedVmArgs.append(librariesOption + '=' + ':'.join(resolved_lib_args)) return substitutedVmArgs diff --git a/mx.sulong/mx_testsuites.py b/mx.sulong/mx_testsuites.py index 48a6504d6..190f671f1 100644 --- a/mx.sulong/mx_testsuites.py +++ b/mx.sulong/mx_testsuites.py @@ -285,54 +285,71 @@ def renameBenchmarkFiles(directory): mx_subst.path_substitutions.register_no_arg('sulong_include', lambda: os.path.join(mx.suite('sulong').dir, 'include')) +def cached(meth): + cached_attr = '_cached_' + meth.__name__ + def _cached_meth(self): + if not hasattr(self, cached_attr): + setattr(self, cached_attr, meth(self)) + return getattr(self, cached_attr) + return _cached_meth + +class Dependency(object): + def __init__(self, isFulfilled): + self._isFulfilled = isFulfilled + + @cached + def isFulfilled(self): + return self._isFulfilled() + +Dependency.RUST = Dependency(lambda: mx_sulong.checkRust()) # pylint: disable=W0108 +Dependency.DRAGONEGG = Dependency(lambda: mx_sulong.dragonEggPath() is not None and os.path.exists(mx_sulong.dragonEggPath()) and mx_sulong.getGCC(optional=True) is not None) class SulongTestSuite(mx.NativeProject): - def __init__(self, suite, name, deps, workingSets, subDir, results=None, output=None, buildRef=True, **args): + def __init__(self, suite, name, deps, workingSets, subDir, results=None, output=None, buildRef=True, libraries=(), **args): d = os.path.join(suite.dir, subDir) # use common Makefile for all test suites mx.NativeProject.__init__(self, suite, name, subDir, [], deps, workingSets, results, output, d, **args) self.vpath = True self.buildRef = buildRef + self.libraries = libraries - @staticmethod - def haveDragonegg(): - if not hasattr(SulongTestSuite, '_haveDragonegg'): - SulongTestSuite._haveDragonegg = mx_sulong.dragonEggPath() is not None and os.path.exists(mx_sulong.dragonEggPath()) and mx_sulong.getGCC(optional=True) is not None - return SulongTestSuite._haveDragonegg - - @staticmethod - def haveRust(): - if not hasattr(SulongTestSuite, '_haveRust'): - SulongTestSuite._haveRust = mx_sulong.checkRust() - return SulongTestSuite._haveRust - + @cached def getTests(self): - if not hasattr(self, '_tests'): - self._tests = [] - extensions = ['.c', '.cpp', '.rs'] - root = os.path.join(self.dir, self.name) - for path, _, files in os.walk(root): - for f in files: - absPath = os.path.join(path, f) - relPath = os.path.relpath(absPath, root) - test, ext = os.path.splitext(relPath) - if ext in extensions: - if ext == '.rs' and not SulongTestSuite.haveRust(): - mx.warn('Rust is not available, not building Rust test files') - extensions.remove('.rs') - continue - self._tests.append(test) - return self._tests - + tests = [] + extensions = ['.c', '.cpp', '.rs'] + root = os.path.join(self.dir, self.name) + for path, _, files in os.walk(root): + for f in files: + absPath = os.path.join(path, f) + relPath = os.path.relpath(absPath, root) + test, ext = os.path.splitext(relPath) + if ext in extensions: + if ext == '.rs' and not Dependency.RUST.isFulfilled(): + mx.warn('Rust is not available, not building Rust test files') + extensions.remove('.rs') + continue + tests.append(test) + return tests + + @cached def getVariants(self): - if not hasattr(self, '_variants'): - self._variants = [] - for v in self.variants: - if 'gcc' in v and not SulongTestSuite.haveDragonegg(): - mx.warn('Could not find dragonegg, not building test variant "%s"' % v) - continue - self._variants.append(v) - return self._variants - + variants = [] + for v in self.variants: + if 'gcc' in v and not Dependency.DRAGONEGG.isFulfilled(): + mx.warn('Could not find dragonegg, not building test variant "%s"' % v) + continue + variants.append(v) + return variants + + @cached + def getLibEntries(self): + return [lib['lib'] for lib in self.libraries if all(getattr(Dependency, dep).isFulfilled() for dep in lib['dependencies'])] + + @cached + def getLibsLocations(self): + if self.getLibEntries(): + root = os.path.join(self.dir, self.name) + return [subdir for subdir in os.listdir(root) if os.path.isdir(os.path.join(root, subdir))] + return [] def getBuildEnv(self, replaceVar=mx_subst.path_substitutions): env = super(SulongTestSuite, self).getBuildEnv(replaceVar=replaceVar) @@ -341,8 +358,10 @@ def getBuildEnv(self, replaceVar=mx_subst.path_substitutions): env['TESTS'] = ' '.join(self.getTests()) env['VARIANTS'] = ' '.join(self.getVariants()) env['BUILD_REF'] = '1' if self.buildRef else '0' + env['LIBS_LOCATIONS'] = ' '.join(self.getLibsLocations()) + env['LIB_ENTRIES'] = ' '.join(self.getLibEntries()) env['SULONG_MAKE_CLANG_IMPLICIT_ARGS'] = mx_sulong.getClangImplicitArgs() - if SulongTestSuite.haveDragonegg(): + if Dependency.DRAGONEGG.isFulfilled(): env['DRAGONEGG'] = mx_sulong.dragonEggPath() env['DRAGONEGG_GCC'] = mx_sulong.getGCC() env['DRAGONEGG_LLVMAS'] = mx_sulong.findLLVMProgramForDragonegg("llvm-as") @@ -356,4 +375,6 @@ def getResults(self, replaceVar=mx_subst.results_substitutions): self.results.append(os.path.join(t, 'ref.out')) for v in self.getVariants(): self.results.append(os.path.join(t, v + '.bc')) + for l in self.getLibsLocations(): + self.results.append(os.path.join(l, 'libs')) return super(SulongTestSuite, self).getResults(replaceVar=replaceVar) diff --git a/mx.sulong/suite.py b/mx.sulong/suite.py index 61ddc12a1..5d0f6625b 100644 --- a/mx.sulong/suite.py +++ b/mx.sulong/suite.py @@ -367,6 +367,9 @@ "subDir" : "tests", "class" : "SulongTestSuite", "variants" : ["O0"], + "libraries" : [ + {"lib" : "", "dependencies" : ["RUST"]} + ], "buildEnv" : { "OS" : "", }, diff --git a/tests/Makefile b/tests/Makefile index 441392670..9d0b34e0b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -38,8 +38,10 @@ endif BC_TARGETS:=$(foreach var,$(VARIANTS),$(TESTS:%=%/$(var).bc)) CXXFLAGS=-std=c++11 -stdlib=libc++ -DLIBCXXABI_SILENT_TERMINATE +LIBS_TARGETS:=$(LIBS_LOCATIONS:%=%/libs) + .PHONY: default -default: $(REF_TARGETS) $(BC_TARGETS) +default: $(REF_TARGETS) $(BC_TARGETS) $(LIBS_TARGETS) ifeq ($(OS), darwin) EMBED_BC=-fembed-bitcode @@ -101,3 +103,7 @@ $(eval $(call OPT_RULES,O3,-O3)) %_MEM2REG.bc: %.bc $(QUIETLY) opt -o $@ -mem2reg $< + +%/libs: + @mkdir -p $(shell dirname $@) + @echo "$(LIB_ENTRIES)" > $@ From 9188bc30a3e3fa7e04fc91b5ff5883ee8c2959cc Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 15:37:51 -0700 Subject: [PATCH 06/13] Look up test suite path via path substitutions when configuring unit tests. --- mx.sulong/mx_sulong.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index e07b320b2..1407e8131 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -114,7 +114,7 @@ def _unittest_config_participant(config): (vmArgs, mainClass, mainClassArgs) = config libs = ['/'] - (testSuitePath,), _ = extract_arg_values(vmArgs, '-Dsulongtest.testSuitePath') + testSuitePath = mx_subst.path_substitutions.substitute('') # gather library dependencies for libs_file in glob.glob(os.path.join(testSuitePath, '*', 'libs')): From 248ab6c02d94f10522a07b6af0d7803adbbab80d Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Fri, 13 Apr 2018 15:38:40 -0700 Subject: [PATCH 07/13] Link library dependencies of unit tests when testing LLVM image. --- mx.sulong/mx_sulong.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 1407e8131..6591476ca 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -113,19 +113,19 @@ def _unittest_config_participant(config): (vmArgs, mainClass, mainClassArgs) = config - libs = ['/'] testSuitePath = mx_subst.path_substitutions.substitute('') - - # gather library dependencies - for libs_file in glob.glob(os.path.join(testSuitePath, '*', 'libs')): - with open(libs_file, 'r') as l: - libs += l.readline().split() - - vmArgs = getCommonOptions(True, [mx_subst.path_substitutions.substitute(lib) for lib in libs]) + vmArgs + libs = [mx_subst.path_substitutions.substitute('/')] + getUnittestLibraryDependencies(testSuitePath) + vmArgs = getCommonOptions(True, libs) + vmArgs return (vmArgs, mainClass, mainClassArgs) add_config_participant(_unittest_config_participant) +def getUnittestLibraryDependencies(libs_files_path): + libs = [] + for libs_file in glob.glob(os.path.join(libs_files_path, '*', 'libs')): + with open(libs_file, 'r') as l: + libs += l.readline().split() + return [mx_subst.path_substitutions.substitute(lib) for lib in libs] def _sulong_gate_runner(args, tasks): with Task('CheckCopyright', tasks, tags=['style']) as t: @@ -176,6 +176,9 @@ def testLLVMImage(image, imageArgs=None, testFilter=None, libPath=True, test=Non aotArgs = [] if libPath: aotArgs += [mx_subst.path_substitutions.substitute('-Dllvm.home=')] + libs = getUnittestLibraryDependencies(mx_subst.path_substitutions.substitute('')) + if libs: + aotArgs += ['-Dpolyglot.llvm.libraries=' + ':'.join(libs)] if imageArgs is not None: aotArgs += imageArgs if aotArgs: From 6d6ebe962157f311a21c7e1e1b8dfe0daffa8505 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Tue, 10 Jul 2018 10:01:23 -0700 Subject: [PATCH 08/13] Label sulongrust as test project. --- mx.sulong/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mx.sulong/suite.py b/mx.sulong/suite.py index 5d0f6625b..c52e75b42 100644 --- a/mx.sulong/suite.py +++ b/mx.sulong/suite.py @@ -373,6 +373,7 @@ "buildEnv" : { "OS" : "", }, + "testProject" : True, }, "com.oracle.truffle.llvm.tests.libc" : { "subDir" : "tests", From 4a45ad16fc1d4e5cfd7a49417bde5ca15d7178a6 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Tue, 10 Jul 2018 10:02:03 -0700 Subject: [PATCH 09/13] Enable Rust in travis gate. --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6fcafc2fc..70933f9c0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,6 @@ cache: dist: trusty sudo: required language: generic -language: rust - - 1.19.0 install: - cd .. - gem install mdl @@ -48,6 +46,8 @@ matrix: fast_finish: true include: - env: LLVM_VER=3.8 GATE_TAGS='sulongBasic' COMPILE_COMMAND='mx build' + language: rust + rust: 1.19.0 addons: apt: packages: @@ -121,6 +121,8 @@ matrix: - libc++1 - libc++-dev - env: LLVM_VER=3.8 GATE_TAGS='fullbuild' + language: rust + rust: 1.19.0 addons: apt: packages: @@ -191,6 +193,8 @@ matrix: - libc++1 - libc++-dev - env: LLVM_VER=3.8 DOWNSTREAM_REPO='https://github.com/graalvm/graal.git' DOWNSTREAM_SUITE='vm' DYNAMIC_IMPORTS='sulong,/substratevm' NATIVE_IMAGE_TESTING='True' DOWNSTREAM_COMMAND='--disable-polyglot --disable-libpolyglot gate -B=--force-deprecation-as-warning --tags build,sulong' + language: rust + rust: 1.19.0 addons: apt: packages: From d73f44df41b5137a80468ace0d367ed07309ca72 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Tue, 10 Jul 2018 12:38:03 -0700 Subject: [PATCH 10/13] Adjust linking of library dependencies to work with graalvm test. --- mx.sulong/mx_sulong.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 6591476ca..3df94bb32 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -178,7 +178,7 @@ def testLLVMImage(image, imageArgs=None, testFilter=None, libPath=True, test=Non aotArgs += [mx_subst.path_substitutions.substitute('-Dllvm.home=')] libs = getUnittestLibraryDependencies(mx_subst.path_substitutions.substitute('')) if libs: - aotArgs += ['-Dpolyglot.llvm.libraries=' + ':'.join(libs)] + aotArgs += ['--llvm.libraries=' + ':'.join(libs)] if imageArgs is not None: aotArgs += imageArgs if aotArgs: From 009c4c8b2240c86847c19737cf8db8b0dbce1f41 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Thu, 12 Jul 2018 10:41:15 -0700 Subject: [PATCH 11/13] Apply small improvements to checkRust and findRustLibrary. --- mx.sulong/mx_sulong.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 3df94bb32..3bd80220b 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -297,8 +297,8 @@ def dragonEggGPP(args=None): return mx.run(executeCommand + args) def checkRust(): - """checks if a Rust installation is available; tries to install the active toolchain if it is missing""" - if os.environ.get('SULONG_USE_RUSTC', 'true') == 'false' or not which('rustc'): + """checks if a Rust installation is available; may try to install the active toolchain if it is missing""" + if os.environ.get('SULONG_USE_RUSTC', 'true') == 'false' or which('rustc') is None: return False rustc = subprocess.Popen(['rustc', '--version'], stdout=subprocess.PIPE) @@ -639,13 +639,12 @@ def findGCCProgram(gccProgram, optional=False): return installedProgram def findRustLibrary(name, on_failure=exit): - """looks up the path to the given Rust library for the active toolchain; tries to install the active toolchain if it is missing; exits if installation fails""" + """looks up the path to the given Rust library for the active toolchain; may try to install the active toolchain if it is missing; exits by default if installation fails""" if not checkRust(): on_failure('Rust is not available') return None - rustc = subprocess.Popen(['rustc', '--print', 'sysroot'], stdout=subprocess.PIPE) - sysroot = rustc.communicate()[0].rstrip() + sysroot = subprocess.check_output(['rustc', '--print', 'sysroot']).rstrip() lib_paths = glob.glob(os.path.join(sysroot, 'lib', mx.add_lib_suffix('lib' + name + '-*'))) if len(lib_paths) == 0: on_failure('could not find Rust library ' + name) From ca34e1a0b85a76fd88304ba6622049c3084e6571 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Thu, 12 Jul 2018 17:26:25 -0700 Subject: [PATCH 12/13] Add rustfmt to style gate. --- .rustfmt.toml | 56 +++++++++++++++++++ .travis.yml | 6 ++ mx.sulong/mx_sulong.py | 53 ++++++++++++++---- mx.sulong/mx_testsuites.py | 2 +- .../rust/test001.rs | 33 ++++++++++- .../rust/test002.rs | 33 ++++++++++- 6 files changed, 167 insertions(+), 16 deletions(-) create mode 100644 .rustfmt.toml diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 000000000..b416dbb9d --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,56 @@ +max_width = 100 +hard_tabs = false +tab_spaces = 4 +newline_style = "Unix" +use_small_heuristics = "Default" +indent_style = "Block" +wrap_comments = false +comment_width = 80 +normalize_comments = false +format_strings = false +empty_item_single_line = true +struct_lit_single_line = true +fn_single_line = false +where_single_line = false +imports_indent = "Block" +imports_layout = "Mixed" +merge_imports = false +reorder_imports = true +reorder_modules = true +reorder_impl_items = false +type_punctuation_density = "Wide" +space_before_colon = false +space_after_colon = true +spaces_around_ranges = false +binop_separator = "Front" +remove_nested_parens = true +combine_control_expr = true +struct_field_align_threshold = 0 +match_arm_blocks = true +force_multiline_blocks = false +fn_args_density = "Tall" +brace_style = "SameLineWhere" +control_brace_style = "AlwaysSameLine" +trailing_semicolon = true +trailing_comma = "Vertical" +match_block_trailing_comma = false +blank_lines_upper_bound = 1 +blank_lines_lower_bound = 0 +merge_derives = true +use_try_shorthand = false +use_field_init_shorthand = false +force_explicit_abi = true +condense_wildcard_suffixes = false +color = "Auto" +required_version = "0.8.2" +unstable_features = false +disable_all_formatting = false +skip_children = false +hide_parse_errors = false +error_on_line_overflow = false +error_on_unformatted = false +report_todo = "Never" +report_fixme = "Never" +ignore = [] +emit_mode = "Files" +make_backup = false diff --git a/.travis.yml b/.travis.yml index 70933f9c0..9a6e0b0f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,9 @@ cache: dist: trusty sudo: required language: generic +before_install: +# Travis does not auto-delete the rust-toolchain file + - rm rust-toolchain install: - cd .. - gem install mdl @@ -31,6 +34,7 @@ install: - mx sforceimports # the style gate needs the full commit history for checking copyright years - test "$GATE_TAGS" != "style" || git fetch --unshallow + - test "$GATE_TAGS" != "style" || rustup component add rustfmt-preview --toolchain=$TRAVIS_RUST_VERSION script: - cd ../llvmDir - ln -s /usr/bin/clang-$LLVM_VER clang @@ -110,6 +114,8 @@ matrix: - libc++1 - libc++-dev - env: LLVM_VER=3.8 GATE_TAGS='style' + language: rust + rust: nightly addons: apt: packages: diff --git a/mx.sulong/mx_sulong.py b/mx.sulong/mx_sulong.py index 3bd80220b..d1d518c41 100644 --- a/mx.sulong/mx_sulong.py +++ b/mx.sulong/mx_sulong.py @@ -111,6 +111,11 @@ '4.0', ] +# the file paths that we want to check with rustfmt +rustfmtCheckPaths = [ + join(_testDir, "com.oracle.truffle.llvm.tests.sulongrust") +] + def _unittest_config_participant(config): (vmArgs, mainClass, mainClassArgs) = config testSuitePath = mx_subst.path_substitutions.substitute('') @@ -134,6 +139,8 @@ def _sulong_gate_runner(args, tasks): t.abort('Copyright errors found. Please run "mx checkcopyrights --primary -- --fix" to fix them.') with Task('ClangFormat', tasks, tags=['style', 'clangformat']) as t: if t: clangformatcheck() + with Task('Rustfmt', tasks, tags=['style', 'rustfmt']) as t: + if t: rustfmtcheck() with Task('TestBenchmarks', tasks, tags=['benchmarks', 'sulongMisc']) as t: if t: mx_testsuites.runSuite('shootout') with Task('TestTypes', tasks, tags=['type', 'sulongMisc']) as t: @@ -217,14 +224,22 @@ def runLLVMUnittests(unittest_runner): def clangformatcheck(args=None): """ Performs a format check on the include/truffle.h file """ for f in clangFormatCheckPaths: - checkCFiles(f) + checkFiles(f, checkCFile, ['.c', '.cpp', '.h', '.hpp']) -def checkCFiles(targetDir): +def rustfmtcheck(args=None): + """ Performs a format check on the Rust test files """ + if not checkRustComponent('rustfmt'): + mx.warn("'rustfmt' is not available") + return + for f in rustfmtCheckPaths: + checkFiles(f, checkRustFile, ['rs']) + +def checkFiles(targetDir, fileChecker, exts): error = False for path, _, files in os.walk(targetDir): for f in files: - if f.endswith('.c') or f.endswith('.cpp') or f.endswith('.h') or f.endswith('.hpp'): - if not checkCFile(path + '/' + f): + if f.endswith(tuple(exts)): + if not fileChecker(path + '/' + f): error = True if error: mx.log_error("found formatting errors!") @@ -247,6 +262,22 @@ def checkCFile(targetFile): return False return True +def checkRustFile(targetFile): + """ Checks the formatting of a Rust file and returns True if the formatting is okay """ + if not checkRustComponent('rustfmt'): + exit("Unable to find 'rustfmt' executable") + returncode_check = mx.run(['rustfmt', '--check', targetFile], nonZeroIsFatal=False) + if returncode_check == 1: + # formatted code differs from existing code or error occured; try to modify the file to the right format + returncode_replace = mx.run(['rustfmt', targetFile], nonZeroIsFatal=False) + if returncode_replace == 0: + mx.log('modified formatting in {0}'.format(targetFile)) + return False + elif returncode_check == 0: + return True + mx.log_error('encountered parsing errors or operational errors when trying to format {0}'.format(targetFile)) + return False + # platform dependent def pullLLVMBinaries(args=None): """downloads the LLVM binaries""" @@ -296,14 +327,14 @@ def dragonEggGPP(args=None): executeCommand = [getGPP(), "-fplugin=" + dragonEggPath(), '-fplugin-arg-dragonegg-emit-ir'] return mx.run(executeCommand + args) -def checkRust(): - """checks if a Rust installation is available; may try to install the active toolchain if it is missing""" - if os.environ.get('SULONG_USE_RUSTC', 'true') == 'false' or which('rustc') is None: +def checkRustComponent(componentName): + """checks if a Rust component is available; may try to install the active toolchain if it is missing""" + if (componentName == 'rustc' and os.environ.get('SULONG_USE_RUSTC', 'true') == 'false') or which(componentName) is None: return False - rustc = subprocess.Popen(['rustc', '--version'], stdout=subprocess.PIPE) - rustc.communicate() - return rustc.returncode == 0 + component = subprocess.Popen([componentName, '--version'], stdout=subprocess.PIPE) + component.communicate() + return component.returncode == 0 def which(program, searchPath=None): def is_exe(fpath): @@ -640,7 +671,7 @@ def findGCCProgram(gccProgram, optional=False): def findRustLibrary(name, on_failure=exit): """looks up the path to the given Rust library for the active toolchain; may try to install the active toolchain if it is missing; exits by default if installation fails""" - if not checkRust(): + if not checkRustComponent('rustc'): on_failure('Rust is not available') return None diff --git a/mx.sulong/mx_testsuites.py b/mx.sulong/mx_testsuites.py index 190f671f1..2570978d8 100644 --- a/mx.sulong/mx_testsuites.py +++ b/mx.sulong/mx_testsuites.py @@ -301,7 +301,7 @@ def __init__(self, isFulfilled): def isFulfilled(self): return self._isFulfilled() -Dependency.RUST = Dependency(lambda: mx_sulong.checkRust()) # pylint: disable=W0108 +Dependency.RUST = Dependency(lambda: mx_sulong.checkRustComponent('rustc')) # pylint: disable=W0108 Dependency.DRAGONEGG = Dependency(lambda: mx_sulong.dragonEggPath() is not None and os.path.exists(mx_sulong.dragonEggPath()) and mx_sulong.getGCC(optional=True) is not None) class SulongTestSuite(mx.NativeProject): diff --git a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs index b51564175..892813f8a 100644 --- a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs +++ b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test001.rs @@ -1,3 +1,32 @@ -fn main(){ - std::process::exit(42); +/* + * Copyright (c) 2018, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +fn main() { + std::process::exit(42); } diff --git a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs index f116527e2..2652cdf87 100644 --- a/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs +++ b/tests/com.oracle.truffle.llvm.tests.sulongrust/rust/test002.rs @@ -1,3 +1,32 @@ -fn main(){ - println!("Hello World!"); +/* + * Copyright (c) 2018, Oracle and/or its affiliates. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors may be used to + * endorse or promote products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +fn main() { + println!("Hello World!"); } From 074465ad2ab6d028031069087a1e7f51679d4418 Mon Sep 17 00:00:00 2001 From: Arif Anatol Celik Date: Mon, 30 Jul 2018 06:26:26 -0700 Subject: [PATCH 13/13] Add gate check for Rust 1.27.1. --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9a6e0b0f8..aae2bdae2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,6 +62,8 @@ matrix: - libc++1 - libc++-dev - env: LLVM_VER=3.9 GATE_TAGS='sulongBasic' COMPILE_COMMAND='mx build' + language: rust + rust: 1.27.1 addons: apt: sources: