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/build.sbt b/build.sbt index 0e92dbc20..b3721d359 100644 --- a/build.sbt +++ b/build.sbt @@ -105,7 +105,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 map { _ -> "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, @@ -117,6 +121,18 @@ val root = (project in file(".")). projectID in Universal <<= moduleID ) +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/Copy.java b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/Copy.java new file mode 100644 index 000000000..31c7e95d7 --- /dev/null +++ b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/Copy.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 Copy { + 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/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..eee31ce46 --- /dev/null +++ b/java9-rt-export/src/main/java/io/github/retronym/java9rtexport/Export.java @@ -0,0 +1,48 @@ +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 --global-base"); + System.err.println(" Prints sbt global base."); + System.exit(-1); + } + String destination = args[0]; + if (destination.equals("--global-base")) { + Path defaultGlobalBase = Paths.get(System.getProperty("user.home"), ".sbt", "0.13"); + String globalBase = System.getProperty("sbt.global.base", defaultGlobalBase.toString()); + System.out.println(globalBase); + 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(); + Copy.copyDirectory(next, zipfs.getPath("/")); + } + } + } catch (IOException e) { + e.printStackTrace(); + System.exit(-1); + } + } +} diff --git a/src/universal/bin/sbt-launch-lib.bash b/src/universal/bin/sbt-launch-lib.bash index 6b73f7f28..f51460a2a 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,8 +151,16 @@ 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'" + rtexport=$(rt_export_file) + sbt_global_dir=$("$java_cmd" ${JAVA_OPTS} ${SBT_OPTS:-$default_sbt_opts} ${java_args[@]} \ + -jar "$rtexport" --global-base) + java9_ext=$(echo "$sbt_global_dir/java9-rt-ext") + java9_rt=$(echo "$java9_ext/rt.jar") + vlog "[process_args] sbt_global_dir = '$sbt_global_dir'" + vlog "[process_args] java9_rt = '$java9_rt'" } # Detect that we have java installed. @@ -174,6 +186,21 @@ checkJava() { fi } +copyRt() { + if [[ "$java_version" > "8" ]] && [[ ! -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 + if [[ "$java_version" > "8" ]]; then + addJava "-Dscala.ext.dirs=${java9_ext}" + fi +} + run() { # no jar? download it. @@ -191,6 +218,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