diff --git a/.java-version b/.java-version new file mode 100644 index 000000000..625934097 --- /dev/null +++ b/.java-version @@ -0,0 +1 @@ +1.8 diff --git a/.travis.yml b/.travis.yml index e8c434f57..b58de08cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ script: scala: - 2.10.3 jdk: - - oraclejdk7 + - oraclejdk8 notifications: email: - sbt-dev-bot@googlegroups.com diff --git a/build.sbt b/build.sbt index 5dcf76bda..a446273de 100644 --- a/build.sbt +++ b/build.sbt @@ -109,7 +109,11 @@ val root = (project in file(".")). // Universal ZIP download install. packageName in Universal := packageName.value, // needs to be set explicitly due to a bug in native-packager version in Universal := sbtVersionToRelease, - mappings in Universal += { sbtLaunchJar.value -> "bin/sbt-launch.jar" }, + mappings in Universal ++= { + val launchJar = sbtLaunchJar.value + val rtExportJar = (packageBin in Compile in java9rtexport).value + Seq(launchJar -> "bin/sbt-launch.jar", rtExportJar -> "bin/java9-rt-export.jar") + }, // Misccelaneous publishing stuff... projectID in Debian := moduleID.value, @@ -121,6 +125,18 @@ val root = (project in file(".")). projectID in Universal := moduleID.value ) +lazy val java9rtexport = (project in file("java9-rt-export")) + .settings( + name := "java9-rt-export", + autoScalaLibrary := false, + crossPaths := false, + description := "Exports the contents of the Java 9. JEP-220 runtime image to a JAR for compatibility with older tools.", + homepage := Some(url("http://github.com/retronym/" + name.value)), + startYear := Some(2017), + licenses += ("Scala license", url(homepage.value.get.toString + "/blob/master/LICENSE")), + mainClass in Compile := Some("io.github.retronym.java9rtexport.Export") + ) + def downloadUrlForVersion(v: String) = (v split "[^\\d]" flatMap (i => catching(classOf[Exception]) opt (i.toInt))) match { case Array(0, 11, 3, _*) => "http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.11.3-2/sbt-launch.jar" case Array(0, 11, x, _*) if x >= 3 => "http://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/"+v+"/sbt-launch.jar" diff --git a/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/Export.java b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/Export.java new file mode 100644 index 000000000..6bb468531 --- /dev/null +++ b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/Export.java @@ -0,0 +1,54 @@ +package io.github.retronym.java9rtexport; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class Export { + public static void main(String[] args) { + try { + if (args.length == 0) { + System.err.println("Usage:"); + System.err.println(" java -jar java9-rt-export-*.jar $HOME/.sbt/java9-rt-ext/rt.jar"); + System.err.println(" Exports rt.jar to the specified path."); + System.err.println(""); + System.err.println(" java -jar java9-rt-export-*.jar --rt-ext-dir"); + System.err.println(" Prints sbt global base."); + System.exit(-1); + } + String destination = args[0]; + Path defaultGlobalBase = Paths.get(System.getProperty("user.home"), ".sbt", "0.13"); + String globalBase = System.getProperty("sbt.global.base", defaultGlobalBase.toString()); + if (destination.equals("--global-base")) { + System.out.println(globalBase); + System.exit(0); + } + if (destination.equals("--rt-ext-dir")) { + String v = System.getProperty("java.vendor") + "_" + System.getProperty("java.version"); + v = v.replaceAll("\\W", "_").toLowerCase(); + Path rtExtDir = Paths.get(globalBase, "java9-rt-ext-" + v); + System.out.println(rtExtDir.toString()); + System.exit(0); + } + FileSystem fileSystem = FileSystems.getFileSystem(URI.create("jrt:/")); + Path path = fileSystem.getPath("/modules"); + Path destPath = Paths.get(destination); + URI uri = URI.create( "jar:" + destPath.toUri() ); + Map env = new HashMap<>(); + env.put( "create", "true" ); + try ( FileSystem zipfs = FileSystems.newFileSystem( uri, env ) ) { + Iterator iterator = Files.list(path).iterator(); + while(iterator.hasNext()) { + Path next = iterator.next(); + IO.copyDirectory(next, zipfs.getPath("/")); + } + } + } catch (IOException e) { + e.printStackTrace(); + System.exit(-1); + } + } +} diff --git a/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/IO.java b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/IO.java new file mode 100644 index 000000000..a57eaa392 --- /dev/null +++ b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/IO.java @@ -0,0 +1,49 @@ +package io.github.retronym.java9rtexport; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.*; +import java.nio.file.attribute.*; +import java.util.EnumSet; + +import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; + +public class IO { + public static void copyDirectory(final Path source, final Path target) + throws IOException { + Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS), + Integer.MAX_VALUE, new FileVisitor() { + + @Override + public FileVisitResult preVisitDirectory(Path dir, + BasicFileAttributes sourceBasic) throws IOException { + + String relative = source.relativize(dir).toString(); + if (!Files.exists(target.getFileSystem().getPath(relative))) + Files.createDirectory(target.getFileSystem().getPath(relative)); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, + BasicFileAttributes attrs) throws IOException { + String relative = source.relativize(file).toString(); + Files.copy(file, target.getFileSystem().getPath(relative), COPY_ATTRIBUTES, REPLACE_EXISTING); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException e) throws IOException { + throw e; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException { + if (e != null) throw e; + return FileVisitResult.CONTINUE; + } + }); + } + +} diff --git a/src/universal/bin/sbt-launch-lib.bash b/src/universal/bin/sbt-launch-lib.bash index 6b73f7f28..c58f445da 100755 --- a/src/universal/bin/sbt-launch-lib.bash +++ b/src/universal/bin/sbt-launch-lib.bash @@ -38,6 +38,10 @@ acquire_sbt_jar () { fi } +rt_export_file () { + echo "${sbt_bin_dir}/java9-rt-export.jar" +} + execRunner () { # print the arguments one to a line, quoting any containing spaces [[ $verbose || $debug ]] && echo "# Executing command line:" && { @@ -147,7 +151,8 @@ process_args () { process_my_args "${myargs[@]}" } - java_version=$("$java_cmd" -Xmx512M -version 2>&1 | sed 's/.*version "\([0-9]*\)\.\([0-9]*\)\..*"/\1.\2/; 1q') + ## parses 1.7, 1.8, 9, etc out of java version "1.8.0_91" + java_version=$("$java_cmd" -Xmx512M -version 2>&1 | sed 's/.*version "\([0-9]*\)\(\.[0-9]*\)\{0,1\}\(.*\)*"/\1\2/; 1q') vlog "[process_args] java_version = '$java_version'" } @@ -174,6 +179,25 @@ checkJava() { fi } +copyRt() { + if [[ "$java_version" > "8" ]]; then + rtexport=$(rt_export_file) + java9_ext=$("$java_cmd" ${JAVA_OPTS} ${SBT_OPTS:-$default_sbt_opts} ${java_args[@]} \ + -jar "$rtexport" --rt-ext-dir) + java9_rt=$(echo "$java9_ext/rt.jar") + vlog "[copyRt] java9_rt = '$java9_rt'" + if [[ ! -f "$java9_rt" ]]; then + echo Copying runtime jar. + execRunner "$java_cmd" \ + ${JAVA_OPTS} \ + ${SBT_OPTS:-$default_sbt_opts} \ + ${java_args[@]} \ + -jar "$rtexport" \ + "${java9_rt}" + fi + addJava "-Dscala.ext.dirs=${java9_ext}" + fi +} run() { # no jar? download it. @@ -191,6 +215,9 @@ run() { # TODO - java check should be configurable... checkJava "1.6" + # Java 9 support + copyRt + #If we're in cygwin, we should use the windows config, and terminal hacks if [[ "$CYGWIN_FLAG" == "true" ]]; then stty -icanon min 1 -echo > /dev/null 2>&1 diff --git a/src/universal/bin/sbt.bat b/src/universal/bin/sbt.bat index 0f7a3e9a3..12178b7c7 100644 --- a/src/universal/bin/sbt.bat +++ b/src/universal/bin/sbt.bat @@ -1,95 +1,150 @@ -@REM SBT launcher script -@REM -@REM Environment: -@REM JAVA_HOME - location of a JDK home dir (mandatory) -@REM SBT_OPTS - JVM options (optional) -@REM Configuration: -@REM sbtconfig.txt found in the SBT_HOME. - -@REM ZOMG! We need delayed expansion to build up CFG_OPTS later -@setlocal enabledelayedexpansion - -@echo off -set SBT_HOME=%~dp0 - -rem FIRST we load the config file of extra options. -set FN=%SBT_HOME%\..\conf\sbtconfig.txt -set CFG_OPTS= -FOR /F "tokens=* eol=# usebackq delims=" %%i IN ("%FN%") DO ( - set DO_NOT_REUSE_ME=%%i - rem ZOMG (Part #2) WE use !! here to delay the expansion of - rem CFG_OPTS, otherwise it remains "" for this loop. - set CFG_OPTS=!CFG_OPTS! !DO_NOT_REUSE_ME! -) - -rem poor man's jenv (which is not available on Windows) -IF DEFINED JAVA_HOMES ( - IF EXIST .java-version FOR /F %%A IN (.java-version) DO ( - SET JAVA_HOME=%JAVA_HOMES%\%%A - SET JDK_HOME=%JAVA_HOMES%\%%A - ) -) -rem must set PATH or wrong javac is used for java projects -IF DEFINED JAVA_HOME SET "PATH=%JAVA_HOME%\bin;%PATH%" - -rem users can set JAVA_OPTS via .jvmopts (sbt-extras style) -IF EXIST .jvmopts FOR /F %%A IN (.jvmopts) DO ( - SET JAVA_OPTS=%%A !JAVA_OPTS! -) - -rem We use the value of the JAVACMD environment variable if defined -set _JAVACMD=%JAVACMD% - -if "%_JAVACMD%"=="" ( - if not "%JAVA_HOME%"=="" ( - if exist "%JAVA_HOME%\bin\java.exe" set "_JAVACMD=%JAVA_HOME%\bin\java.exe" - ) -) - -if "%_JAVACMD%"=="" set _JAVACMD=java - -rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config. -set _JAVA_OPTS=%JAVA_OPTS% -if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=%CFG_OPTS% - -:args_loop -if "%~1" == "" goto args_end - -if "%~1" == "-jvm-debug" ( - set JVM_DEBUG=true - set /a JVM_DEBUG_PORT=5005 2>nul >nul -) else if "!JVM_DEBUG!" == "true" ( - set /a JVM_DEBUG_PORT=%1 2>nul >nul - if not "%~1" == "!JVM_DEBUG_PORT!" ( - set SBT_ARGS=!SBT_ARGS! %1 - ) -) else ( - set SBT_ARGS=!SBT_ARGS! %1 -) - -shift -goto args_loop -:args_end - -if defined JVM_DEBUG_PORT ( - set _JAVA_OPTS=!_JAVA_OPTS! -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=!JVM_DEBUG_PORT! -) - -call :run %SBT_ARGS% - -if ERRORLEVEL 1 goto error -goto end - -:run - -"%_JAVACMD%" %_JAVA_OPTS% %SBT_OPTS% -cp "%SBT_HOME%sbt-launch.jar" xsbt.boot.Boot %* -goto :eof - -:error -@endlocal -exit /B 1 - - -:end -@endlocal -exit /B 0 +@REM SBT launcher script +@REM +@REM Environment: +@REM JAVA_HOME - location of a JDK home dir (mandatory) +@REM SBT_OPTS - JVM options (optional) +@REM Configuration: +@REM sbtconfig.txt found in the SBT_HOME. + +@REM ZOMG! We need delayed expansion to build up CFG_OPTS later +@setlocal enabledelayedexpansion + +@echo off +set SBT_HOME=%~dp0 + +rem FIRST we load the config file of extra options. +set FN=%SBT_HOME%\..\conf\sbtconfig.txt +set CFG_OPTS= +FOR /F "tokens=* eol=# usebackq delims=" %%i IN ("%FN%") DO ( + set DO_NOT_REUSE_ME=%%i + rem ZOMG (Part #2) WE use !! here to delay the expansion of + rem CFG_OPTS, otherwise it remains "" for this loop. + set CFG_OPTS=!CFG_OPTS! !DO_NOT_REUSE_ME! +) + +rem poor man's jenv (which is not available on Windows) +IF DEFINED JAVA_HOMES ( + IF EXIST .java-version FOR /F %%A IN (.java-version) DO ( + SET JAVA_HOME=%JAVA_HOMES%\%%A + SET JDK_HOME=%JAVA_HOMES%\%%A + ) +) +rem must set PATH or wrong javac is used for java projects +IF DEFINED JAVA_HOME SET "PATH=%JAVA_HOME%\bin;%PATH%" + +rem users can set JAVA_OPTS via .jvmopts (sbt-extras style) +IF EXIST .jvmopts FOR /F %%A IN (.jvmopts) DO ( + SET JAVA_OPTS=%%A !JAVA_OPTS! +) + +rem We use the value of the JAVACMD environment variable if defined +set _JAVACMD=%JAVACMD% + +if "%_JAVACMD%"=="" ( + if not "%JAVA_HOME%"=="" ( + if exist "%JAVA_HOME%\bin\java.exe" set "_JAVACMD=%JAVA_HOME%\bin\java.exe" + ) +) + +if "%_JAVACMD%"=="" set _JAVACMD=java + +rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config. +set _JAVA_OPTS=%JAVA_OPTS% +if "%_JAVA_OPTS%"=="" set _JAVA_OPTS=%CFG_OPTS% + +:args_loop +if "%~1" == "" goto args_end + +if "%~1" == "-jvm-debug" ( + set JVM_DEBUG=true + set /a JVM_DEBUG_PORT=5005 2>nul >nul +) else if "!JVM_DEBUG!" == "true" ( + set /a JVM_DEBUG_PORT=%1 2>nul >nul + if not "%~1" == "!JVM_DEBUG_PORT!" ( + set SBT_ARGS=!SBT_ARGS! %1 + ) +) else ( + set SBT_ARGS=!SBT_ARGS! %1 +) + +shift +goto args_loop +:args_end + +if defined JVM_DEBUG_PORT ( + set _JAVA_OPTS=!_JAVA_OPTS! -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=!JVM_DEBUG_PORT! +) + +call :process + +call :checkjava + +call :copyrt + +call :run %SBT_ARGS% + +if ERRORLEVEL 1 goto error +goto end + +:run + +"%_JAVACMD%" %_JAVA_OPTS% %SBT_OPTS% -cp "%SBT_HOME%sbt-launch.jar" xsbt.boot.Boot %* +goto :eof + +:error +@endlocal +exit /B 1 + + +:end +@endlocal +exit /B 0 + +:process +rem parses 1.7, 1.8, 9, etc out of java version "1.8.0_91" +"%_JAVACMD%" -Xmx512M -version 2> "%TEMP%.\out.txt" +set JAVA_VERSION=0 +findstr /c:"version \"9" "%TEMP%.\out.txt" +if /I %ERRORLEVEL% EQU 0 (set JAVA_VERSION=9) +findstr /c:"version \"1.8" "%TEMP%.\out.txt" +if /I %ERRORLEVEL% EQU 0 (set JAVA_VERSION=1.8) +findstr /c:"version \"1.7" "%TEMP%.\out.txt" +if /I %ERRORLEVEL% EQU 0 (set JAVA_VERSION=1.7) +findstr /c:"version \"1.6" "%TEMP%.\out.txt" +if /I %ERRORLEVEL% EQU 0 (set JAVA_VERSION=1.6) +findstr /c:"version \"1.5" "%TEMP%.\out.txt" +if /I %ERRORLEVEL% EQU 0 (set JAVA_VERSION=1.5) + +exit /B 0 + +:checkjava +set required_version=1.6 +if /I "%JAVA_VERSION%" GEQ "%required_version%" ( + exit /B 0 +) +echo. +echo The java installation you have is not up to date +echo sbt requires at least version %required_version%+, you have +echo version %JAVA_VERSION% +echo. +echo Please go to http://www.java.com/getjava/ and download +echo a valid Java Runtime and install before running sbt. +echo. +exit /B 1 + +:copyrt +if /I "%JAVA_VERSION%" GEQ "9" ( + set rtexport=%SBT_HOME%java9-rt-export.jar + + "%_JAVACMD%" %_JAVA_OPTS% %SBT_OPTS% -jar "%rtexport%" --rt-ext-dir > "%TEMP%.\rtext.txt" + set /p java9_ext= < "%TEMP%.\rtext.txt" + set java9_rt=%java9_ext%\rt.jar + + if not exist "%java9_rt%" ( + echo Copying runtime jar. + mkdir "%java9_ext%" + "%_JAVACMD%" %_JAVA_OPTS% %SBT_OPTS% -jar "%rtexport%" "%java9_rt%" + ) + set _JAVA_OPTS=!_JAVA_OPTS! -Dscala.ext.dirs="%java9_ext%" +) +exit /B 0