diff options
author | Paul Phillips <paulp@improving.org> | 2011-11-13 01:56:10 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-11-13 01:56:10 +0000 |
commit | b6a300f3ac965285583ed39348ad43abb6df019e (patch) | |
tree | 9e919340b1ab94d9b849ca1d49b7437924404bf1 /src | |
parent | ea5aac152dab47e7e4aa37224a0b8a609b6d9a0c (diff) | |
download | scala-b6a300f3ac965285583ed39348ad43abb6df019e.tar.gz scala-b6a300f3ac965285583ed39348ad43abb6df019e.tar.bz2 scala-b6a300f3ac965285583ed39348ad43abb6df019e.zip |
Working on the runners.
Removed assumption that bash is in /bin. Removed --posix option to bash.
Modernized shell constructs: $() instead of ``, [[ ]] instead of [ ].
Added -debug option for all runners which will show you the exact java
command line being run before running it. Added -usebootcp to complement
-nobootcp, and made regular classpath the default on cygwin. Quoted more
things to give us a fighting chance against spaces and parens in paths.
I took the waste-half-a-day step of installing vmware fusion so I could
install windows so I could install cygwin so I could install scala
under cygwin so I could see if it still worked. Seems to. We still
desperately need some way of testing not only everything I'm attempting
to address in this pile of patches but everything which is most likely
now regressing.
:javap now sort of works on windows (not for repl-defined classes as
yet) if JAVA_HOME is set such that I can find tools.jar. Closes SI-4959.
(Risks breaking and) references SI-2092. References SI-622 since that
shouldn't be hard to get working.
Diffstat (limited to 'src')
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", |