From c31583e4f8f19a6c2d060b6a75b274050439c203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martynas=20Mickevi=C4=8Dius?= Date: Wed, 18 Apr 2018 16:28:43 +0100 Subject: [PATCH] Discovery of java homes --- .../contraband-scala/sbt/JavaVersion.scala | 40 +++++++++++++++ main/src/main/contraband/main.contra | 6 +++ main/src/main/scala/sbt/Defaults.scala | 4 ++ main/src/main/scala/sbt/Keys.scala | 4 ++ .../main/scala/sbt/internal/CrossJava.scala | 50 +++++++++++++++++++ .../sbt-test/java/home-discovery/build.sbt | 5 ++ sbt/src/sbt-test/java/home-discovery/test | 1 + 7 files changed, 110 insertions(+) create mode 100644 main/src/main/contraband-scala/sbt/JavaVersion.scala create mode 100644 main/src/main/scala/sbt/internal/CrossJava.scala create mode 100644 sbt/src/sbt-test/java/home-discovery/build.sbt create mode 100644 sbt/src/sbt-test/java/home-discovery/test diff --git a/main/src/main/contraband-scala/sbt/JavaVersion.scala b/main/src/main/contraband-scala/sbt/JavaVersion.scala new file mode 100644 index 000000000..68d3941f1 --- /dev/null +++ b/main/src/main/contraband-scala/sbt/JavaVersion.scala @@ -0,0 +1,40 @@ +/** + * This code is generated using [[http://www.scala-sbt.org/contraband/ sbt-contraband]]. + */ + +// DO NOT EDIT MANUALLY +package sbt +final class JavaVersion private ( + val vendor: Option[String], + val version: String) extends Serializable { + + + + override def equals(o: Any): Boolean = o match { + case x: JavaVersion => (this.vendor == x.vendor) && (this.version == x.version) + case _ => false + } + override def hashCode: Int = { + 37 * (37 * (37 * (17 + "sbt.JavaVersion".##) + vendor.##) + version.##) + } + override def toString: String = { + "JavaVersion(" + vendor + ", " + version + ")" + } + private[this] def copy(vendor: Option[String] = vendor, version: String = version): JavaVersion = { + new JavaVersion(vendor, version) + } + def withVendor(vendor: Option[String]): JavaVersion = { + copy(vendor = vendor) + } + def withVendor(vendor: String): JavaVersion = { + copy(vendor = Option(vendor)) + } + def withVersion(version: String): JavaVersion = { + copy(version = version) + } +} +object JavaVersion { + def apply(version: String): JavaVersion = new JavaVersion(None, version) + def apply(vendor: Option[String], version: String): JavaVersion = new JavaVersion(vendor, version) + def apply(vendor: String, version: String): JavaVersion = new JavaVersion(Option(vendor), version) +} diff --git a/main/src/main/contraband/main.contra b/main/src/main/contraband/main.contra index eb9e9f42c..10ec4a469 100644 --- a/main/src/main/contraband/main.contra +++ b/main/src/main/contraband/main.contra @@ -17,3 +17,9 @@ enum PluginTrigger { AllRequirements NoTrigger } + +type JavaVersion { + vendor: String + version: String! + #xcompanion def apply(version: String): JavaVersion = new JavaVersion(None, version) +} diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 4a8a34f1a..c4fa875ac 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -69,6 +69,7 @@ import sbt.librarymanagement.syntax._ import sbt.util.InterfaceUtil.{ toJavaFunction => f1 } import sbt.util._ import sbt.util.CacheImplicits._ +import scala.collection.immutable.ListMap import scala.concurrent.duration.FiniteDuration import scala.util.control.NonFatal import scala.xml.NodeSeq @@ -159,6 +160,9 @@ object Defaults extends BuildCommon { scalaHome :== None, apiURL := None, javaHome :== None, + discoveredJavaHomes := sbt.internal.CrossJava.discoverJavaHomes, + javaHomes :== ListMap.empty, + fullJavaHomes := discoveredJavaHomes.value ++ javaHomes.value, testForkedParallel :== false, javaOptions :== Nil, sbtPlugin :== false, diff --git a/main/src/main/scala/sbt/Keys.scala b/main/src/main/scala/sbt/Keys.scala index 82191f556..751540de7 100644 --- a/main/src/main/scala/sbt/Keys.scala +++ b/main/src/main/scala/sbt/Keys.scala @@ -271,6 +271,10 @@ object Keys { val outputStrategy = settingKey[Option[sbt.OutputStrategy]]("Selects how to log output when running a main class.").withRank(DSetting) val connectInput = settingKey[Boolean]("If true, connects standard input when running a main class forked.").withRank(CSetting) val javaHome = settingKey[Option[File]]("Selects the Java installation used for compiling and forking. If None, uses the Java installation running the build.").withRank(ASetting) + val discoveredJavaHomes = settingKey[Map[JavaVersion, File]]("Discovered Java home directories") + val javaHomes = settingKey[Map[JavaVersion, File]]("The user-defined additional Java home directories") + val fullJavaHomes = taskKey[Map[JavaVersion, File]]("Combines discoveredJavaHomes and custom javaHomes.").withRank(CTask) + val javaOptions = taskKey[Seq[String]]("Options passed to a new JVM when forking.").withRank(BPlusTask) val envVars = taskKey[Map[String, String]]("Environment variables used when forking a new JVM").withRank(BTask) diff --git a/main/src/main/scala/sbt/internal/CrossJava.scala b/main/src/main/scala/sbt/internal/CrossJava.scala new file mode 100644 index 000000000..c93d44257 --- /dev/null +++ b/main/src/main/scala/sbt/internal/CrossJava.scala @@ -0,0 +1,50 @@ +/* + * sbt + * Copyright 2011 - 2017, Lightbend, Inc. + * Copyright 2008 - 2010, Mark Harrah + * Licensed under BSD-3-Clause license (see LICENSE) + */ + +package sbt +package internal + +import java.io.File +import scala.collection.immutable.ListMap +import sbt.io.IO +import sbt.io.syntax._ + +private[sbt] object CrossJava { + def discoverJavaHomes: ListMap[JavaVersion, File] = { + val configs = Vector(JavaDiscoverConfig.linux, JavaDiscoverConfig.macOS) + ListMap(configs flatMap { _.javaHomes }: _*) + } + + sealed trait JavaDiscoverConf { + def javaHomes: Vector[(JavaVersion, File)] + } + + object JavaDiscoverConfig { + val linux = new JavaDiscoverConf { + val base: File = file("/usr") / "lib" / "jvm" + val JavaHomeDir = """java-([0-9]+)-.*""".r + def javaHomes: Vector[(JavaVersion, File)] = + wrapNull(base.list()).collect { + case dir @ JavaHomeDir(ver) => JavaVersion(ver) -> (base / dir) + } + } + + val macOS = new JavaDiscoverConf { + val base: File = file("/Library") / "Java" / "JavaVirtualMachines" + val JavaHomeDir = """jdk-?(1\.)?([0-9]+).*""".r + def javaHomes: Vector[(JavaVersion, File)] = + wrapNull(base.list()).collect { + case dir @ JavaHomeDir(m, n) => + JavaVersion(n) -> (base / dir / "Contents" / "Home") + } + } + } + + def wrapNull(a: Array[String]): Vector[String] = + if (a eq null) Vector() + else a.toVector +} diff --git a/sbt/src/sbt-test/java/home-discovery/build.sbt b/sbt/src/sbt-test/java/home-discovery/build.sbt new file mode 100644 index 000000000..b5d79caeb --- /dev/null +++ b/sbt/src/sbt-test/java/home-discovery/build.sbt @@ -0,0 +1,5 @@ +Global / javaHomes += JavaVersion("6") -> file("/good/old/times/java-6") + +TaskKey[Unit]("check") := { + assert(fullJavaHomes.value(JavaVersion("6")).getAbsolutePath.contains("java-6")) +} diff --git a/sbt/src/sbt-test/java/home-discovery/test b/sbt/src/sbt-test/java/home-discovery/test new file mode 100644 index 000000000..15675b169 --- /dev/null +++ b/sbt/src/sbt-test/java/home-discovery/test @@ -0,0 +1 @@ +> check