diff options
5 files changed, 122 insertions, 73 deletions
diff --git a/src/compiler/scala/reflect/internal/ClassfileConstants.scala b/src/compiler/scala/reflect/internal/ClassfileConstants.scala index 3eb6c55848..136350ebbb 100644 --- a/src/compiler/scala/reflect/internal/ClassfileConstants.scala +++ b/src/compiler/scala/reflect/internal/ClassfileConstants.scala @@ -32,6 +32,11 @@ object ClassfileConstants { * * All interface methods must have their `ACC_ABSTRACT` and * `ACC_PUBLIC` flags set. + * + * Note for future reference: see this thread on ACC_SUPER and + * how its enforcement differs on the android vm. + * https://groups.google.com/forum/?hl=en#!topic/jvm-languages/jVhzvq8-ZIk + * */ // Class Field Method final val JAVA_ACC_PUBLIC = 0x0001 // X X X final val JAVA_ACC_PRIVATE = 0x0002 // X X diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl index 72d6ba1bab..4275ef7ba1 100644 --- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl +++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl @@ -1,4 +1,4 @@ -#!/bin/bash --posix +#!/usr/bin/env bash # ############################################################################## # Copyright 2002-2011, LAMP/EPFL @@ -8,6 +8,17 @@ # PARTICULAR PURPOSE. ############################################################################## +findScalaHome () { + # see #2092 + local SOURCE="${BASH_SOURCE[0]}" + while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done + ( cd -P "$( dirname "$SOURCE" )"/.. && pwd ) +} +execCommand () { + [[ -n $SCALA_RUNNER_DEBUG ]] && echo "" && for arg in "$@@"; do echo "$arg"; done && echo ""; + "$@@" +} + # Not sure what the right default is here: trying nonzero. scala_exit_status=127 saved_stty="" @@ -15,7 +26,8 @@ saved_stty="" # restore stty settings (echo in particular) function restoreSttySettings() { if [[ -n $SCALA_RUNNER_DEBUG ]]; then - echo "restoring stty: $saved_stty" + echo "restoring stty:" + echo "$saved_stty" fi stty $saved_stty @@ -23,10 +35,8 @@ function restoreSttySettings() { } function onExit() { - if [[ "$saved_stty" != "" ]]; then - restoreSttySettings - exit $scala_exit_status - fi + [[ "$saved_stty" != "" ]] && restoreSttySettings + exit $scala_exit_status } # to reenable echo if we are interrupted before completing. @@ -39,69 +49,60 @@ if [[ ! $? ]]; then saved_stty="" fi if [[ -n $SCALA_RUNNER_DEBUG ]]; then - echo "saved stty: $saved_stty" + echo "saved stty:" + echo "$saved_stty" fi -cygwin=false; -case "`uname`" in - CYGWIN*) cygwin=true ;; -esac +unset cygwin +if uname | grep -q ^CYGWIN; then + cygwin="$(uname)" +fi # Finding the root folder for this Scala distribution -SOURCE=$0; -SCRIPT=`basename "$SOURCE"`; -while [ -h "$SOURCE" ]; do - SCRIPT=`basename "$SOURCE"`; - LOOKUP=`ls -ld "$SOURCE"`; - TARGET=`expr "$LOOKUP" : '.*-> \(.*\)$'`; - if expr "${TARGET:-.}/" : '/.*/$' > /dev/null; then - SOURCE=${TARGET:-.}; - else - SOURCE=`dirname "$SOURCE"`/${TARGET:-.}; - fi; -done; +SCALA_HOME="$(findScalaHome)" +SEP=":" -# see #2092 -SCALA_HOME=`dirname "$SOURCE"` -SCALA_HOME=`cd "$SCALA_HOME"; pwd -P` -SCALA_HOME=`cd "$SCALA_HOME"/..; pwd` +# Possible additional command line options +CYGWIN_OPT="" +EMACS_OPT="" +[[ -n "$EMACS" ]] && EMACS_OPT="-Denv.emacs=$EMACS" # Remove spaces from SCALA_HOME on windows -if $cygwin; then - SCALA_HOME=`cygpath --windows --short-name "$SCALA_HOME"` - SCALA_HOME=`cygpath --unix "$SCALA_HOME"` +if [[ -n "$cygwin" ]]; then + SCALA_HOME="$(shome="$(cygpath --windows --short-name "$SCALA_HOME")" ; cygpath --unix "$shome")" +# elif uname |grep -q ^MINGW; then +# SEP=";" fi # Constructing the extension classpath TOOL_CLASSPATH="@classpath@" -if [ -z "$TOOL_CLASSPATH" ] ; then +if [[ -z "$TOOL_CLASSPATH" ]]; then for ext in "$SCALA_HOME"/lib/* ; do - if [ -z "$TOOL_CLASSPATH" ] ; then + if [[ -z "$TOOL_CLASSPATH" ]]; then TOOL_CLASSPATH="$ext" else - TOOL_CLASSPATH="$TOOL_CLASSPATH:$ext" + TOOL_CLASSPATH="${TOOL_CLASSPATH}${SEP}${ext}" fi done fi -CYGWIN_JLINE_TERMINAL= -if $cygwin; then - if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then +if [[ -n "$cygwin" ]]; then + if [[ "$OS" = "Windows_NT" ]] && cygpath -m .>/dev/null 2>/dev/null ; then format=mixed else format=windows fi - SCALA_HOME=`cygpath --$format "$SCALA_HOME"` - TOOL_CLASSPATH=`cygpath --path --$format "$TOOL_CLASSPATH"` + SCALA_HOME="$(cygpath --$format "$SCALA_HOME")" + TOOL_CLASSPATH="$(cygpath --path --$format "$TOOL_CLASSPATH")" case "$TERM" in rxvt* | xterm*) stty -icanon min 1 -echo - CYGWIN_JLINE_TERMINAL="-Djline.terminal=scala.tools.jline.UnixTerminal" + CYGWIN_OPT="-Djline.terminal=scala.tools.jline.UnixTerminal" ;; esac fi -[ -n "$JAVA_OPTS" ] || JAVA_OPTS="@javaflags@" +[[ -n "$JAVA_OPTS" ]] || JAVA_OPTS="@javaflags@" # break out -D and -J options and add them to JAVA_OPTS as well # so they reach the underlying JVM in time to do some good. The @@ -109,11 +110,21 @@ fi declare -a java_args declare -a scala_args -# default to the boot classpath for speed. -CPSELECT="-Xbootclasspath/a:" -USEJAVACP=false +# default to the boot classpath for speed, except on cygwin/mingw. +unset usebootcp +if [[ -z $cygwin ]]; then + usebootcp="true" +fi + +classpathArgs () { + if [[ -n $usebootcp ]]; then + echo "-Xbootclasspath/a:$TOOL_CLASSPATH" + else + echo "-classpath $TOOL_CLASSPATH" + fi +} -while [ $# -gt 0 ]; do +while [[ $# -gt 0 ]]; do case "$1" in -D*) # pass to scala as well: otherwise we lose it sometimes when we @@ -130,12 +141,19 @@ while [ $# -gt 0 ]; do shift ;; -toolcp) - TOOL_CLASSPATH="$TOOL_CLASSPATH:$2" + TOOL_CLASSPATH="${TOOL_CLASSPATH}${SEP}${2}" shift 2 ;; -nobootcp) - CPSELECT="-classpath " - USEJAVACP=true + unset usebootcp + shift + ;; + -usebootcp) + usebootcp="true" + shift + ;; + -debug) + SCALA_RUNNER_DEBUG=1 shift ;; *) @@ -148,18 +166,22 @@ done # reset "$@@" to the remaining args set -- "${scala_args[@@]}" -if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then +if [[ -z "$JAVACMD" && -n "$JAVA_HOME" && -x "$JAVA_HOME/bin/java" ]]; then JAVACMD="$JAVA_HOME/bin/java" fi -"${JAVACMD:=java}" \ +# note that variables which may intentionally be empty must not +# be quoted: otherwise an empty string will appear as a command line +# argument, and java will think that is the program to run. +execCommand \ + "${JAVACMD:=java}" \ $JAVA_OPTS \ "${java_args[@@]}" \ - ${CPSELECT}${TOOL_CLASSPATH} \ - -Dscala.usejavacp="$USEJAVACP" \ + $(classpathArgs) \ -Dscala.home="$SCALA_HOME" \ - -Denv.emacs="$EMACS" \ - $CYGWIN_JLINE_TERMINAL \ + -Dscala.usejavacp=true \ + $EMACS_OPT \ + $CYGWIN_OPT \ @properties@ @class@ @toolflags@ "$@@" # record the exit status lest it be overwritten: diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala index c83ccfeef1..d33be5bca0 100644 --- a/src/compiler/scala/tools/nsc/Properties.scala +++ b/src/compiler/scala/tools/nsc/Properties.scala @@ -22,4 +22,9 @@ object Properties extends scala.util.PropertiesTrait { // derived values def isEmacsShell = propOrEmpty("env.emacs") != "" def fileEndings = fileEndingString.split("""\|""").toList + + // System property java.home is the JRE root. + // Environment variable JAVA_HOME is (supposed to be) the jdk root. + // We need the latter to find javac, tools.jar, etc. + def jdkHome = envOrElse("JAVA_HOME", javaHome) } diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index ce74b2a8c3..391d5ab8ee 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -17,9 +17,10 @@ import scala.collection.mutable.ListBuffer import scala.concurrent.ops import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream } import interpreter._ -import io.{ File, Sources } +import io.{ File, Sources, Directory } import scala.reflect.NameTransformer._ -import util.ScalaClassLoader._ +import util.ScalaClassLoader +import ScalaClassLoader._ import scala.tools.util._ /** The Scala interactive shell. It provides a read-eval-print loop @@ -374,7 +375,17 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } } - protected def newJavap() = new JavapClass(intp.classLoader, new IMain.ReplStrippingWriter(intp)) { + private def addToolsJarToLoader() = { + val javaHome = Directory(sys.env("JAVA_HOME")) + val tools = javaHome / "lib" / "tools.jar" + if (tools.isFile) { + echo("Found tools.jar, adding for use by javap.") + ScalaClassLoader.fromURLs(Seq(tools.toURL), intp.classLoader) + } + else intp.classLoader + } + + protected def newJavap() = new JavapClass(addToolsJarToLoader(), new IMain.ReplStrippingWriter(intp)) { override def tryClass(path: String): Array[Byte] = { val hd :: rest = path split '.' toList; // If there are dots in the name, the first segment is the diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala index 711e3f0935..5403e1954f 100644 --- a/src/partest/scala/tools/partest/nest/Worker.scala +++ b/src/partest/scala/tools/partest/nest/Worker.scala @@ -12,6 +12,7 @@ import java.io._ import java.net.URL import java.util.{ Timer, TimerTask } +import scala.tools.nsc.Properties.{ jdkHome, javaHome, propOrElse } import scala.util.Properties.{ isWin } import scala.tools.nsc.{ Settings, CompilerCommand, Global } import scala.tools.nsc.io.{ AbstractFile, PlainFile, Path, Directory, File => SFile } @@ -105,14 +106,9 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor val scalaCheckFileManager = new ScalaCheckFileManager(fileManager) var reporter: ConsoleReporter = _ - val timer = new Timer - - val javacCmd = if ((fileManager.JAVAC_CMD.indexOf("${env.JAVA_HOME}") != -1) || - fileManager.JAVAC_CMD.equals("/bin/javac") || - fileManager.JAVAC_CMD.equals("\\bin\\javac")) "javac" - else - fileManager.JAVAC_CMD - + val timer = new Timer + val javaCmd = propOrElse("partest.javacmd", Path(javaHome) / "bin" / "java" path) + val javacCmd = propOrElse("partest.javac_cmd", Path(jdkHome) / "bin" / "javac" path) def cancelTimerTask() = if (currentTimerTask != null) currentTimerTask.cancel() def updateTimerTask(body: => Unit) = { @@ -272,15 +268,16 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor def javac(outDir: File, files: List[File], output: File): Boolean = { // compile using command-line javac compiler - val cmd = "%s -d %s -classpath %s %s".format( + val args = Seq( javacCmd, + "-d", outDir.getAbsolutePath, - join(outDir.toString, CLASSPATH), - files mkString " " - ) + "-classpath", + join(outDir.toString, CLASSPATH) + ) ++ files.map("" + _) - try runCommand(cmd, output) - catch exHandler(output, "javac command '" + cmd + "' failed:\n") + try runCommand(args, output) + catch exHandler(output, "javac command failed:\n" + args.map(" " + _ + "\n").mkString + "\n") } /** Runs command redirecting standard out and @@ -290,7 +287,15 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor NestUI.verbose("running command:\n"+command) (command #> outFile !) == 0 } + def runCommand(args: Seq[String], outFile: File): Boolean = { + NestUI.verbose("running command:\n"+args.map(" " + _ + "\n").mkString) + (Process(args) #> outFile !) == 0 + } + private def q(s: String) = { + val quot = "\"" + if ((s == "") || (s.head == '"')) s else quot + s + quot + } def execTest(outDir: File, logFile: File, classpathPrefix: String = ""): Boolean = { // check whether there is a ".javaopts" file val argsFile = new File(logFile.getParentFile, fileBase + ".javaopts") @@ -325,7 +330,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor "-Dpartest.cwd="+outDir.getParent, "-Dpartest.test-path="+testFullPath, "-Dpartest.testname="+fileBase, - "-Djavacmd="+JAVACMD, + "-Djavacmd="+javaCmd, "-Djavaccmd="+javacCmd, "-Duser.language=en -Duser.country=US" ) ++ extras @@ -333,10 +338,11 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor val classpath = if (classpathPrefix != "") join(classpathPrefix, CLASSPATH) else CLASSPATH val cmd = ( List( - JAVACMD, + javaCmd, JAVA_OPTS, argString, - "-classpath " + join(outDir.toString, classpath) + "-classpath", + join(outDir.toString, classpath) ) ++ propertyOptions ++ List( "scala.tools.nsc.MainGenericRunner", "-usejavacp", |