diff options
author | Li Haoyi <haoyi.sg@gmail.com> | 2018-03-18 10:35:57 -0700 |
---|---|---|
committer | Li Haoyi <haoyi.sg@gmail.com> | 2018-03-18 10:35:57 -0700 |
commit | 3715c7bfb88de8daa86cd663d22057ec776cedcc (patch) | |
tree | 0a85083bcdb27867110e33c05c15ac13ae2865a9 | |
parent | 350a3115afca590bee6311dbed4a657fe9cca375 (diff) | |
parent | 0063444b422e317b9ee68c789f9b3224dcf28825 (diff) | |
download | mill-3715c7bfb88de8daa86cd663d22057ec776cedcc.tar.gz mill-3715c7bfb88de8daa86cd663d22057ec776cedcc.tar.bz2 mill-3715c7bfb88de8daa86cd663d22057ec776cedcc.zip |
Merge branch 'master' of github.com:lihaoyi/mill
29 files changed, 367 insertions, 129 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index 8fa75778..a8c4da3a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,20 +9,40 @@ clone_folder: c:\mill environment: matrix: + - COMPILER: cygwin + CYGWIN_DIR: cygwin64 + JAVA_HOME: C:\Program Files\Java\jdk9 - COMPILER: msys2 - PLATFORM: x64 MSYS2_ARCH: x86_64 MSYS2_DIR: msys64 MSYSTEM: MINGW64 - BIT: 64 - JAVA_HOME: 'C:\Program Files\Java\jdk1.8.0' - PATH: '%JAVA_HOME%\bin;C:\bin;C:\%MSYS2_DIR%\%MSYSTEM%\bin;C:\%MSYS2_DIR%\usr\bin;%PATH%' + JAVA_HOME: C:\Program Files\Java\jdk1.8.0 + - COMPILER: msys2 + MSYS2_ARCH: x86_64 + MSYS2_DIR: msys64 + MSYSTEM: MINGW64 + JAVA_HOME: C:\Program Files\Java\jdk9 cache: - - '%LOCALAPPDATA%\Coursier\cache' + - build.sc -> '%LOCALAPPDATA%\Coursier\cache' install: - - bash -lc "mkdir /c/bin && curl -Lo /c/bin/mill https://github.com/lihaoyi/mill/releases/download/0.1.4/0.1.4-12-f5250d" + - SET MILL_URL=https://github.com/lihaoyi/mill/releases/download/0.1.6/0.1.6-3-43d230 build_script: - - bash -lc "cd /c/mill && mill -i all main.test scalajslib.test" + - if [%COMPILER%]==[msys2] ( + SET "PATH=%JAVA_HOME%\bin;C:\%MSYS2_DIR%\%MSYSTEM%\bin;C:\%MSYS2_DIR%\usr\bin;%PATH%" && + C:\%MSYS2_DIR%\usr\bin\bash -lc 'mkdir -p /usr/local/bin' && + C:\%MSYS2_DIR%\usr\bin\bash -lc "curl -Lo /usr/local/bin/mill %MILL_URL%" && + C:\%MSYS2_DIR%\usr\bin\bash -lc 'chmod +x /usr/local/bin/mill' && + C:\%MSYS2_DIR%\usr\bin\bash -lc "cd /c/mill && mill -i all __.publishLocal release" && + C:\%MSYS2_DIR%\usr\bin\bash -lc "cd /c/mill && out/release/dest/mill all main.test scalajslib.test") + - if [%COMPILER%]==[cygwin] ( + SET "PATH=%JAVA_HOME%\bin;C:\%CYGWIN_DIR%\bin;C:\%CYGWIN_DIR%\usr\bin;%PATH%" && + C:\%CYGWIN_DIR%\bin\bash -lc 'mkdir -p /usr/local/bin' && + C:\%CYGWIN_DIR%\bin\bash -lc "curl -Lo /usr/local/bin/mill %MILL_URL%" && + C:\%CYGWIN_DIR%\bin\bash -lc 'sed -i '"'"'0,/-cp "\$0"/{s/-cp "\$0"/-cp `cygpath -w "\$0"`/}; 0,/-cp "\$0"/{s/-cp "\$0"/-cp `cygpath -w "\$0"`/}'"'"' /usr/local/bin/mill' && + C:\%CYGWIN_DIR%\bin\bash -lc 'chmod +x /usr/local/bin/mill' && + C:\%CYGWIN_DIR%\bin\bash -lc "cd /cygdrive/c/mill && mill -i all main.test scalajslib.test") + +skip_branch_with_pr: true
\ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 45373358..3898dbfa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,31 +2,44 @@ language: scala sudo: required dist: trusty -jdk: - - oraclejdk8 - matrix: include: - stage: build env: CI_SCRIPT=ci/test-mill-0.sh + jdk: oraclejdk9 + - stage: build + env: CI_SCRIPT=ci/test-mill-0.sh + jdk: oraclejdk8 - stage: build env: CI_SCRIPT=ci/test-mill-1.sh + jdk: oraclejdk8 - stage: build env: CI_SCRIPT=ci/test-mill-2.sh + jdk: oraclejdk8 - stage: build env: CI_SCRIPT=ci/test-mill-dev.sh + jdk: oraclejdk9 + - stage: build + env: CI_SCRIPT=ci/test-mill-dev.sh + jdk: oraclejdk8 + - stage: build + env: CI_SCRIPT=ci/test-mill-release.sh + jdk: oraclejdk9 - stage: build env: CI_SCRIPT=ci/test-mill-release.sh + jdk: oraclejdk8 - stage: release env: CI_SCRIPT="ci/on-master.py ci/release.sh" + jdk: oraclejdk8 - stage: release env: CI_SCRIPT="ci/on-master.py ci/publish-docs.sh" + jdk: oraclejdk8 script: - - curl -L -o ~/bin/mill https://github.com/lihaoyi/mill/releases/download/0.1.3/0.1.3 && chmod +x ~/bin/mill + - curl -L -o ~/bin/mill https://github.com/lihaoyi/mill/releases/download/0.1.6/0.1.6 && chmod +x ~/bin/mill - export PATH=~/bin/mill:$PATH - "$CI_SCRIPT" cache: directories: - - $HOME/.coursier
\ No newline at end of file + - $HOME/.coursier @@ -69,6 +69,7 @@ trait MillModule extends MillPublishModule{ outer => object clientserver extends MillModule{ def ivyDeps = Agg( + ivy"com.lihaoyi:::ammonite:1.0.5-4-c0cdbaf", ivy"org.scala-sbt.ipcsocket:ipcsocket:1.0.0" ) val test = new Tests(implicitly) @@ -83,7 +84,7 @@ object core extends MillModule { def ivyDeps = Agg( ivy"com.lihaoyi::sourcecode:0.1.4", - ivy"com.lihaoyi:::ammonite:1.0.5", + ivy"com.lihaoyi:::ammonite:1.0.5-4-c0cdbaf", ivy"jline:jline:2.14.5" ) @@ -235,11 +236,13 @@ object dev extends MillModule{ write(outputPath, prependShellScript()) - val perms = java.nio.file.Files.getPosixFilePermissions(outputPath.toNIO) - perms.add(PosixFilePermission.GROUP_EXECUTE) - perms.add(PosixFilePermission.OWNER_EXECUTE) - perms.add(PosixFilePermission.OTHERS_EXECUTE) - java.nio.file.Files.setPosixFilePermissions(outputPath.toNIO, perms) + if (!scala.util.Properties.isWin) { + val perms = java.nio.file.Files.getPosixFilePermissions(outputPath.toNIO) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + java.nio.file.Files.setPosixFilePermissions(outputPath.toNIO, perms) + } PathRef(outputPath) } diff --git a/ci/publish-local.sh b/ci/publish-local.sh index fc9e06b9..c137340d 100755 --- a/ci/publish-local.sh +++ b/ci/publish-local.sh @@ -2,6 +2,6 @@ set -eux -mill all __.publishLocal release +mill -i all __.publishLocal release mv out/release/dest/mill ~/mill-release diff --git a/ci/test-mill-dev.sh b/ci/test-mill-dev.sh index cb83ef00..11d64154 100755 --- a/ci/test-mill-dev.sh +++ b/ci/test-mill-dev.sh @@ -6,7 +6,7 @@ set -eux git clean -xdf # Build Mill using SBT -mill dev.assembly +mill -i dev.assembly # Second build & run tests using Mill out/dev/assembly/dest/mill -i all {clientserver,main,scalalib,scalajslib}.test diff --git a/ci/test-mill-release.sh b/ci/test-mill-release.sh index 3c70410b..8c0aca2f 100755 --- a/ci/test-mill-release.sh +++ b/ci/test-mill-release.sh @@ -11,4 +11,4 @@ git clean -xdf # Second build & run tests using Mill -~/mill-release integration.test "mill.integration.forked.{AcyclicTests,UpickleTests}" +~/mill-release -i integration.test "mill.integration.forked.{AcyclicTests,UpickleTests}" diff --git a/clientserver/src/mill/clientserver/Client.java b/clientserver/src/mill/clientserver/Client.java index 1870c8a4..eab8c5b5 100644 --- a/clientserver/src/mill/clientserver/Client.java +++ b/clientserver/src/mill/clientserver/Client.java @@ -1,29 +1,40 @@ package mill.clientserver; -import org.scalasbt.ipcsocket.UnixDomainSocket; +import io.github.retronym.java9rtexport.Export; +import org.scalasbt.ipcsocket.*; import java.io.*; +import java.net.Socket; +import java.net.URISyntaxException; import java.net.URL; import java.nio.channels.FileChannel; +import java.nio.file.Files; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.Properties; public class Client { - static void initServer(String lockBase) throws IOException{ - StringBuilder selfJars = new java.lang.StringBuilder(); + static void initServer(String lockBase, boolean setJnaNoSys) throws IOException,URISyntaxException{ + ArrayList<String> selfJars = new ArrayList<String>(); ClassLoader current = Client.class.getClassLoader(); while(current != null){ if (current instanceof java.net.URLClassLoader) { URL[] urls = ((java.net.URLClassLoader) current).getURLs(); for (URL url: urls) { - if (selfJars.length() != 0) selfJars.append(':'); - selfJars.append(url); + selfJars.add(new File(url.toURI()).getCanonicalPath()); } } current = current.getParent(); } - + if (!System.getProperty("java.specification.version").startsWith("1.")) { + selfJars.addAll(Arrays.asList(System.getProperty("java.class.path").split(File.pathSeparator))); + File rtFile = new File(lockBase + "/rt-" + System.getProperty("java.version") + ".jar"); + if (!rtFile.exists()) { + Files.copy(Export.export().toPath(), rtFile.toPath()); + } + selfJars.add(rtFile.getCanonicalPath()); + } ArrayList<String> l = new java.util.ArrayList<String>(); l.add("java"); Properties props = System.getProperties(); @@ -32,8 +43,11 @@ public class Client { String k = keys.next(); if (k.startsWith("MILL_")) l.add("-D" + k + "=" + props.getProperty(k)); } + if (setJnaNoSys) { + l.add("-Djna.nosys=true"); + } l.add("-cp"); - l.add(selfJars.toString()); + l.add(String.join(File.pathSeparator, selfJars)); l.add("mill.ServerMain"); l.add(lockBase); new java.lang.ProcessBuilder() @@ -43,6 +57,10 @@ public class Client { .start(); } public static void main(String[] args) throws Exception{ + boolean setJnaNoSys = System.getProperty("jna.nosys") == null; + if (setJnaNoSys) { + System.setProperty("jna.nosys", "true"); + } int index = 0; while (index < 5) { index += 1; @@ -61,8 +79,8 @@ public class Client { @Override public void run() { try{ - initServer(lockBase); - }catch(IOException e){ + initServer(lockBase, setJnaNoSys); + }catch(Exception e){ throw new RuntimeException(e); } } @@ -91,16 +109,26 @@ public class Client { FileOutputStream f = new FileOutputStream(lockBase + "/run"); ClientServer.writeArgs(System.console() != null, args, f); f.close(); - if (locks.processLock.probe()) initServer.run(); + + boolean serverInit = false; + if (locks.processLock.probe()) { + serverInit = true; + initServer.run(); + } while(locks.processLock.probe()) Thread.sleep(3); + // Need to give sometime for Win32NamedPipeSocket to work + // if the server is just initialized + if (serverInit && ClientServer.isWindows) Thread.sleep(250); - UnixDomainSocket ioSocket = null; + Socket ioSocket = null; long retryStart = System.currentTimeMillis(); while(ioSocket == null && System.currentTimeMillis() - retryStart < 1000){ try{ - ioSocket = new UnixDomainSocket(lockBase + "/io"); + ioSocket = ClientServer.isWindows? + new Win32NamedPipeSocket(ClientServer.WIN32_PIPE_PREFIX + new File(lockBase).getName()) + : new UnixDomainSocket(lockBase + "/io"); }catch(Throwable e){ Thread.sleep(1); } @@ -178,7 +206,10 @@ class ClientOutputPumper implements Runnable{ } } }catch(IOException e){ - throw new RuntimeException(e); + // Win32NamedPipeSocket input stream somehow doesn't return -1, + // but throw IOException whose message contains "ReadFile()" with a ccode + if (ClientServer.isWindows && e.getMessage().contains("ReadFile()")) running = false; + else throw new RuntimeException(e); } } diff --git a/clientserver/src/mill/clientserver/ClientServer.java b/clientserver/src/mill/clientserver/ClientServer.java index a8692c61..7af5845b 100644 --- a/clientserver/src/mill/clientserver/ClientServer.java +++ b/clientserver/src/mill/clientserver/ClientServer.java @@ -6,6 +6,14 @@ import java.io.InputStream; import java.io.OutputStream; class ClientServer { + public static boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); + + // Windows named pipe prefix (see https://github.com/sbt/ipcsocket/blob/v1.0.0/README.md) + // Win32NamedPipeServerSocket automatically adds this as a prefix (if it is not already is prefixed), + // but Win32NamedPipeSocket does not + // https://github.com/sbt/ipcsocket/blob/v1.0.0/src/main/java/org/scalasbt/ipcsocket/Win32NamedPipeServerSocket.java#L36 + public static String WIN32_PIPE_PREFIX = "\\\\.\\pipe\\"; + public static String[] parseArgs(InputStream argStream) throws IOException { int argsLength = argStream.read(); diff --git a/clientserver/src/mill/clientserver/Server.scala b/clientserver/src/mill/clientserver/Server.scala index 27c43302..24827ac2 100644 --- a/clientserver/src/mill/clientserver/Server.scala +++ b/clientserver/src/mill/clientserver/Server.scala @@ -3,7 +3,7 @@ package mill.clientserver import java.io._ import java.net.Socket -import org.scalasbt.ipcsocket.{UnixDomainServerSocket, UnixDomainSocket} +import org.scalasbt.ipcsocket._ trait ServerMain[T]{ def main(args0: Array[String]): Unit = { @@ -11,7 +11,7 @@ trait ServerMain[T]{ args0(0), this, () => System.exit(0), - 60000, + 300000, Locks.files(args0(0)) ).run() } @@ -37,18 +37,28 @@ class Server[T](lockBase: String, var running = true while (running) { Server.lockBlock(locks.serverLock){ - new File(lockBase + "/io").delete() - val ioSocket = new UnixDomainServerSocket(lockBase + "/io") + val (serverSocket, socketClose) = if (ClientServer.isWindows) { + val socketName = ClientServer.WIN32_PIPE_PREFIX + new File(lockBase).getName + (new Win32NamedPipeServerSocket(socketName), () => new Win32NamedPipeSocket(socketName).close()) + } else { + val socketName = lockBase + "/io" + new File(socketName).delete() + (new UnixDomainServerSocket(socketName), () => new UnixDomainSocket(socketName).close()) + } + val sockOpt = Server.interruptWith( acceptTimeout, - new UnixDomainSocket(lockBase + "/io").close(), - ioSocket.accept() + socketClose(), + serverSocket.accept() ) sockOpt match{ case None => running = false case Some(sock) => - try handleRun(sock) + try { + handleRun(sock) + serverSocket.close() + } catch{case e: Throwable => e.printStackTrace(originalStdout) } } } @@ -106,7 +116,16 @@ class Server[T](lockBase: String, t.interrupt() t.stop() - clientSocket.close() + + if (ClientServer.isWindows) { + // Closing Win32NamedPipeSocket can often take ~5s + // It seems OK to exit the client early and subsequently + // start up mill client again (perhaps closing the server + // socket helps speed up the process). + val t = new Thread(() => clientSocket.close()) + t.setDaemon(true) + t.start() + } else clientSocket.close() } } object Server{ @@ -161,4 +180,4 @@ class ProxyInputStream(x: => java.io.InputStream) extends java.io.InputStream{ override def read(b: Array[Byte], off: Int, len: Int) = x.read(b, off, len) override def read(b: Array[Byte]) = x.read(b) } -case class WatchInterrupted[T](stateCache: Option[T]) extends Exception
\ No newline at end of file +case class WatchInterrupted[T](stateCache: Option[T]) extends Exception diff --git a/core/src/mill/util/ClassLoader.scala b/core/src/mill/util/ClassLoader.scala new file mode 100644 index 00000000..a1b42158 --- /dev/null +++ b/core/src/mill/util/ClassLoader.scala @@ -0,0 +1,19 @@ +package mill.util + +import java.net.{URL, URLClassLoader} + +import io.github.retronym.java9rtexport.Export + +object ClassLoader { + def create(urls: Seq[URL], parent: java.lang.ClassLoader): URLClassLoader = { + val cl = new URLClassLoader(urls.toArray, parent) + if (!ammonite.util.Util.java9OrAbove) return cl + try { + cl.loadClass("javax.script.ScriptEngineManager") + cl + } catch { + case _: ClassNotFoundException => + new URLClassLoader((urls ++ Some(Export.export().toURI.toURL)).toArray, parent) + } + } +} diff --git a/docs/pages/1 - Intro to Mill.md b/docs/pages/1 - Intro to Mill.md index b912bf14..63b69601 100644 --- a/docs/pages/1 - Intro to Mill.md +++ b/docs/pages/1 - Intro to Mill.md @@ -17,6 +17,14 @@ external subprocesses. ## Installation +### OS X + +Installation via [homebrew](https://github.com/Homebrew/homebrew-core/blob/master/Formula/mill.rb): + +```sh +brew install mill +``` + ### Arch Linux Arch Linux has an [AUR package for mill](https://aur.archlinux.org/packages/mill/): @@ -31,14 +39,14 @@ To get started, download Mill and install it into your system via the following `curl`/`chmod` command: ```bash -sudo curl -L -o /usr/local/bin/mill https://github.com/lihaoyi/mill/releases/download/0.1.4/0.1.4 && sudo chmod +x /usr/local/bin/mill +sudo curl -L -o /usr/local/bin/mill https://github.com/lihaoyi/mill/releases/download/0.1.6/0.1.6 && sudo chmod +x /usr/local/bin/mill ``` ### Development Releases More recent, unstable versions of Mill are also [available](https://github.com/lihaoyi/mill/releases/tag/unstable), if you want -to try out the latest features and improvements that are currently in master. +to try out the latest features and improvements that are currently in master. Come by our [Gitter Channel](https://gitter.im/lihaoyi/mill) if you want to ask questions or say hi! @@ -97,7 +105,7 @@ $ mill foo.repl # start an Ammonite REPL within your project ``` You can run `mill resolve __` to see a full list of the different tasks that are -available, `mill resolve foo._` to see the tasks within `foo`, `mill describe +available, `mill resolve foo._` to see the tasks within `foo`, `mill inspect foo.compile` to see what an individual task depends on, or `mill show foo.scalaVersion` to inspect the output of any task. @@ -320,10 +328,10 @@ mill resolve __ # list every module or task recursively mill resolve foo.__ # list every task recursively within the foo module ``` -### describe +### inspect ```bash -$ mill describe core.run +$ mill inspect core.run core.run(ScalaModule.scala:211) Inputs: @@ -333,26 +341,26 @@ Inputs: core.forkEnv ``` -`describe` is a more verbose version of [resolve](#resolve). In addition to +`inspect` is a more verbose version of [resolve](#resolve). In addition to printing out the name of one-or-more tasks, it also display's it's source location and a list of input tasks. This is very useful for debugging and interactively exploring the structure of your build from the command line. -`describe` also works with the same `_`/`__` wildcard/query syntaxes that +`inspect` also works with the same `_`/`__` wildcard/query syntaxes that [all](#all)/[resolve](#resolve) do: ```bash -mill describe foo.compile -mill describe foo.{compile,run} -mill describe "foo.{compile,run}" -mill describe foo.compile foo.run -mill describe _.compile -mill describe __.compile -mill describe _ -mill describe foo._ -mill describe __ -mill describe foo._ +mill inspect foo.compile +mill inspect foo.{compile,run} +mill inspect "foo.{compile,run}" +mill inspect foo.compile foo.run +mill inspect _.compile +mill inspect __.compile +mill inspect _ +mill inspect foo._ +mill inspect __ +mill inspect foo._ ``` ### show diff --git a/docs/pages/6 - Extending Mill.md b/docs/pages/6 - Extending Mill.md index a6c096a6..75b7643a 100644 --- a/docs/pages/6 - Extending Mill.md +++ b/docs/pages/6 - Extending Mill.md @@ -20,7 +20,7 @@ you're done. For subprocess/filesystem operations, you can use the [Ammonite-Ops](http://ammonite.io/#Ammonite-Ops) library that comes bundled with -Mill, or even plain `java.nio`/`java.lang.Process. Each target gets it's own +Mill, or even plain `java.nio`/`java.lang.Process`. Each target gets it's own [T.ctx().dest](http://www.lihaoyi.com/mill/page/tasks#millutilctxdestctx) folder that you can use to place files without worrying about colliding with other targets. @@ -177,7 +177,7 @@ def idea(ev: Evaluator[Any]) = T.command{ ``` Many built-in tools are implemented as custom evaluator commands: -[all](intro.html#all), [describe](intro.html#describe), +[all](intro.html#all), [inspect](intro.html#inspect), [resolve](intro.html#resolve), [show](intro.html#show). If you want a way to run Mill commands and programmatically manipulate the tasks and outputs, you do so with your own evaluator command. diff --git a/integration/test/src/mill/integration/AcyclicTests.scala b/integration/test/src/mill/integration/AcyclicTests.scala index d1035af0..c117f862 100644 --- a/integration/test/src/mill/integration/AcyclicTests.scala +++ b/integration/test/src/mill/integration/AcyclicTests.scala @@ -25,7 +25,7 @@ class AcyclicTests(fork: Boolean) assert(!brokenCompile) } - 'scala2118 - check("2.11.8") + 'scala2118 - mill.util.TestUtil.disableInJava9OrAbove(check("2.11.8")) 'scala2124 - check("2.12.4") } diff --git a/integration/test/src/mill/integration/UpickleTests.scala b/integration/test/src/mill/integration/UpickleTests.scala index dba6488d..1b83c60f 100644 --- a/integration/test/src/mill/integration/UpickleTests.scala +++ b/integration/test/src/mill/integration/UpickleTests.scala @@ -6,12 +6,19 @@ import utest._ class UpickleTests(fork: Boolean) extends IntegrationTestSuite("MILL_UPICKLE_REPO", "upickle", fork) { val tests = Tests{ initWorkspace() - 'jvm - { - assert(eval("upickleJvm[2.11.11].test")) - val jvmMeta = meta("upickleJvm[2.11.11].test.test") + 'jvm21111 - { + mill.util.TestUtil.disableInJava9OrAbove({ + assert(eval("upickleJvm[2.11.11].test")) + val jvmMeta = meta("upickleJvm[2.11.11].test.test") + assert(jvmMeta.contains("example.ExampleTests.simple")) + assert(jvmMeta.contains("upickle.MacroTests.commonCustomStructures.simpleAdt")) + }) + } + 'jvm2124 - { + assert(eval("upickleJvm[2.12.4].test")) + val jvmMeta = meta("upickleJvm[2.12.4].test.test") assert(jvmMeta.contains("example.ExampleTests.simple")) assert(jvmMeta.contains("upickle.MacroTests.commonCustomStructures.simpleAdt")) - } 'js - { assert(eval("upickleJs[2.12.4].test")) diff --git a/main/src/mill/main/MainModule.scala b/main/src/mill/main/MainModule.scala index 9fa6e4dd..4b0a4354 100644 --- a/main/src/mill/main/MainModule.scala +++ b/main/src/mill/main/MainModule.scala @@ -42,7 +42,7 @@ trait MainModule extends mill.Module{ resolved match{ case Left(err) => Result.Failure(err) case Right(rs) => - for(r <- rs){ + for(r <- rs.sorted) { println(r) } Result.Success(()) diff --git a/main/src/mill/modules/Jvm.scala b/main/src/mill/modules/Jvm.scala index 153e1959..d71cf75c 100644 --- a/main/src/mill/modules/Jvm.scala +++ b/main/src/mill/modules/Jvm.scala @@ -104,7 +104,7 @@ object Jvm { body: ClassLoader => T): T = { val cl = if (classLoaderOverrideSbtTesting) { val outerClassLoader = getClass.getClassLoader - new URLClassLoader(classPath.map(_.toIO.toURI.toURL).toArray, null){ + new URLClassLoader(classPath.map(_.toIO.toURI.toURL).toArray, mill.util.ClassLoader.create(Seq(), null)){ override def findClass(name: String) = { if (name.startsWith("sbt.testing.")){ outerClassLoader.loadClass(name) @@ -114,7 +114,7 @@ object Jvm { } } } else { - new URLClassLoader(classPath.map(_.toIO.toURI.toURL).toArray, null) + mill.util.ClassLoader.create(classPath.map(_.toIO.toURI.toURL).toVector, null) } val oldCl = Thread.currentThread().getContextClassLoader Thread.currentThread().setContextClassLoader(cl) @@ -241,7 +241,7 @@ object Jvm { (implicit ctx: Ctx.Dest) = { val tmp = ctx.dest / "out-tmp.jar" - val baseUri = "jar:file:" + tmp + val baseUri = "jar:" + tmp.toIO.getCanonicalFile.toURI.toASCIIString val hm = new java.util.HashMap[String, String]() base match{ @@ -258,13 +258,18 @@ object Jvm { manifest.write(manifestOut) manifestOut.close() + def isSignatureFile(mapping: String): Boolean = + Set("sf", "rsa", "dsa").exists(ext => mapping.toLowerCase.endsWith(s".$ext")) + for(v <- classpathIterator(inputPaths)){ val (file, mapping) = v val p = zipFs.getPath(mapping) if (p.getParent != null) Files.createDirectories(p.getParent) - val outputStream = newOutputStream(p) - IO.stream(file, outputStream) - outputStream.close() + if (!isSignatureFile(mapping)) { + val outputStream = newOutputStream(p) + IO.stream(file, outputStream) + outputStream.close() + } file.close() } zipFs.close() @@ -278,11 +283,13 @@ object Jvm { IO.stream(read.getInputStream(tmp), outputStream) outputStream.close() - val perms = Files.getPosixFilePermissions(output.toNIO) - perms.add(PosixFilePermission.GROUP_EXECUTE) - perms.add(PosixFilePermission.OWNER_EXECUTE) - perms.add(PosixFilePermission.OTHERS_EXECUTE) - Files.setPosixFilePermissions(output.toNIO, perms) + if (!scala.util.Properties.isWin) { + val perms = Files.getPosixFilePermissions(output.toNIO) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + Files.setPosixFilePermissions(output.toNIO, perms) + } } PathRef(output) @@ -328,11 +335,13 @@ object Jvm { write(outputPath, launcherShellScript(mainClass, classPath.map(_.toString), jvmArgs)) - val perms = Files.getPosixFilePermissions(outputPath.toNIO) - perms.add(PosixFilePermission.GROUP_EXECUTE) - perms.add(PosixFilePermission.OWNER_EXECUTE) - perms.add(PosixFilePermission.OTHERS_EXECUTE) - Files.setPosixFilePermissions(outputPath.toNIO, perms) + if (!scala.util.Properties.isWin) { + val perms = Files.getPosixFilePermissions(outputPath.toNIO) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + Files.setPosixFilePermissions(outputPath.toNIO, perms) + } PathRef(outputPath) } diff --git a/main/test/src/mill/eval/JavaCompileJarTests.scala b/main/test/src/mill/eval/JavaCompileJarTests.scala index 78cf09a5..1ac00c79 100644 --- a/main/test/src/mill/eval/JavaCompileJarTests.scala +++ b/main/test/src/mill/eval/JavaCompileJarTests.scala @@ -114,7 +114,7 @@ object JavaCompileJarTests extends TestSuite{ |test/FooTwo.class |hello.txt |""".stripMargin - assert(jarContents == expectedJarContents) + assert(jarContents.lines.toSeq == expectedJarContents.lines.toSeq) val executed = %%('java, "-cp", evaluator.outPath/'jar/'dest/"out.jar", "test.Foo")(evaluator.outPath).out.string assert(executed == (31337 + 271828) + System.lineSeparator) diff --git a/main/test/src/mill/util/TestUtil.scala b/main/test/src/mill/util/TestUtil.scala index d06c7f6a..d0caade7 100644 --- a/main/test/src/mill/util/TestUtil.scala +++ b/main/test/src/mill/util/TestUtil.scala @@ -78,4 +78,9 @@ object TestUtil { } } } + def disableInJava9OrAbove(f: => Any): Unit = { + if (!ammonite.util.Util.java9OrAbove) { + f + } + } } @@ -107,7 +107,7 @@ mill bridges[2.12.4].publish --credentials foo --gpgPassphrase bar mill all main.test scalalib.test ``` -**Note**: don't forget to put `--all` flag when you run multiple commands, otherwise the only first command will be run, and subsequent commands will be passed as arguments to the first one. +**Note**: don't forget to put `all` flag when you run multiple commands, otherwise the only first command will be run, and subsequent commands will be passed as arguments to the first one. * Run multiple commands with arguments: ```bash @@ -165,7 +165,7 @@ mill all __.test mill all bridges[_].compile ``` -**Note**: When you run multiple targets with `--all` flag, they are not +**Note**: When you run multiple targets with `all` command, they are not guaranteed to run in that exact order. Mill will build task evaluation graph and run targets in correct order. @@ -330,11 +330,60 @@ rm -rf out/ ### master +- Support for non-interactive (client/server) mode on Windows. + + Mill requires an `sh` environment to run on Windows; + it is recommended to use [MSYS2](https://www.msys2.org) on Windows. + + [Cygwin](https://www.cygwin.com) can also be used, + but your mileage may vary when running mill on non-interactive (client/server) mode + (it failed intermittently in mill's AppVeyor tests). + On Cygwin, run the following after downloading mill: + + ```bash + sed -i '0,/-cp "\$0"/{s/-cp "\$0"/-cp `cygpath -w "\$0"`/}; 0,/-cp "\$0"/{s/-cp "\$0"/-cp `cygpath -w "\$0"`/}' <mill-path> + ``` + + Mill also runs on [Git-Bash](https://gitforwindows.org) and [WSL](https://docs.microsoft.com/windows/wsl) + but only on interactive mode. + +### 0.1.6 + +- Fixes for non-interactive (client/server) mode on Java 9 + +### 0.1.5 + - Introduced the `mill plan foo.bar` command, which shows you what the execution plan of running the `foo.bar` task looks like without actually evaluating it. - Mill now generates an `out/mill-profile.json` file containing task-timings, to make it easier to see where your mill evaluation time is going + +- Introduced `ScalaModule#ivyDepsTree` command to show dependencies tree + +- Rename `describe` to `inspect` for consistency with SBT + +- `mill resolve` now prints results sorted alphabetically + +- Node.js configuration can be customised with `ScalaJSModule#nodeJSConfig` + +- Scala.js `fullOpt` now uses Google Closure Compiler after generating the optimized Javascript output + +- Scala.js now supports `NoModule` and `CommonJSModule` module kinds + +- Include `compileIvyDeps` when generating IntelliJ projects + +- Fixed invalid POM generation + +- Support for Java 9 (and 10) + +- Fixes for Windows support + +- Fixed test classes discovery by skipping interfaces + +- Include "optional" artifacts in dependency resolution if they exist + +- `out/{module_name}` now added as a content root in generated IntelliJ project ### 0.1.4 diff --git a/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala b/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala index 5f7bd38b..80f84c3d 100644 --- a/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala +++ b/scalajslib/jsbridges/0.6/src/mill/scalajslib/bridge/ScalaJSBridge.scala @@ -7,19 +7,27 @@ import java.io.File import org.scalajs.core.tools.io.IRFileCache.IRContainer import org.scalajs.core.tools.io._ import org.scalajs.core.tools.jsdep.ResolvedJSDependency -import org.scalajs.core.tools.linker.{ModuleInitializer, StandardLinker, Semantics} +import org.scalajs.core.tools.linker.{ModuleInitializer, StandardLinker, Semantics, ModuleKind => ScalaJSModuleKind} import org.scalajs.core.tools.logging.ScalaConsoleLogger import org.scalajs.jsenv._ import org.scalajs.jsenv.nodejs._ import org.scalajs.testadapter.TestAdapter class ScalaJSBridge extends mill.scalajslib.ScalaJSBridge { - def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean): Unit = { + def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean, moduleKind: ModuleKind): Unit = { val semantics = fullOpt match { case true => Semantics.Defaults.optimized case false => Semantics.Defaults } - val config = StandardLinker.Config().withOptimizer(fullOpt).withClosureCompilerIfAvailable(fullOpt).withSemantics(semantics) + val scalaJSModuleKind = moduleKind match { + case ModuleKind.NoModule => ScalaJSModuleKind.NoModule + case ModuleKind.CommonJSModule => ScalaJSModuleKind.CommonJSModule + } + val config = StandardLinker.Config() + .withOptimizer(fullOpt) + .withClosureCompilerIfAvailable(fullOpt) + .withSemantics(semantics) + .withModuleKind(scalaJSModuleKind) val linker = StandardLinker(config) val sourceSJSIRs = sources.map(new FileVirtualScalaJSIRFile(_)) val jars = libraries.map(jar => IRContainer.Jar(new FileVirtualBinaryFile(jar) with VirtualJarFile)) diff --git a/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala b/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala index 53986f1b..796fe212 100644 --- a/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala +++ b/scalajslib/jsbridges/1.0/src/mill/scalajslib/bridge/ScalaJSBridge.scala @@ -5,19 +5,27 @@ package bridge import java.io.File import org.scalajs.core.tools.io._ -import org.scalajs.core.tools.linker.{ModuleInitializer, StandardLinker, Semantics} +import org.scalajs.core.tools.linker.{ModuleInitializer, StandardLinker, Semantics, ModuleKind => ScalaJSModuleKind} import org.scalajs.core.tools.logging.ScalaConsoleLogger import org.scalajs.jsenv.ConsoleJSConsole import org.scalajs.jsenv.nodejs._ import org.scalajs.testadapter.TestAdapter class ScalaJSBridge extends mill.scalajslib.ScalaJSBridge { - def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean): Unit = { + def link(sources: Array[File], libraries: Array[File], dest: File, main: String, fullOpt: Boolean, moduleKind: ModuleKind): Unit = { val semantics = fullOpt match { case true => Semantics.Defaults.optimized case false => Semantics.Defaults } - val config = StandardLinker.Config().withOptimizer(fullOpt).withClosureCompilerIfAvailable(fullOpt).withSemantics(semantics) + val scalaJSModuleKind = moduleKind match { + case ModuleKind.NoModule => ScalaJSModuleKind.NoModule + case ModuleKind.CommonJSModule => ScalaJSModuleKind.CommonJSModule + } + val config = StandardLinker.Config() + .withOptimizer(fullOpt) + .withClosureCompilerIfAvailable(fullOpt) + .withSemantics(semantics) + .withModuleKind(scalaJSModuleKind) val linker = StandardLinker(config) val cache = new IRFileCache().newCache val sourceIRs = sources.map(FileVirtualScalaJSIRFile) diff --git a/scalajslib/src/mill/scalajslib/ScalaJSBridge.scala b/scalajslib/src/mill/scalajslib/ScalaJSBridge.scala index 20e6542c..507d8af7 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSBridge.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSBridge.scala @@ -12,6 +12,12 @@ sealed trait OptimizeMode object FastOpt extends OptimizeMode object FullOpt extends OptimizeMode +sealed trait ModuleKind +object ModuleKind{ + object NoModule extends ModuleKind + object CommonJSModule extends ModuleKind +} + class ScalaJSWorker { private var scalaInstanceCache = Option.empty[(Long, ScalaJSBridge)] @@ -21,8 +27,8 @@ class ScalaJSWorker { scalaInstanceCache match { case Some((sig, bridge)) if sig == classloaderSig => bridge case _ => - val cl = new URLClassLoader( - toolsClasspath.map(_.toIO.toURI.toURL).toArray, + val cl = mill.util.ClassLoader.create( + toolsClasspath.map(_.toIO.toURI.toURL).toVector, getClass.getClassLoader ) val bridge = cl @@ -40,13 +46,15 @@ class ScalaJSWorker { libraries: Agg[Path], dest: File, main: Option[String], - fullOpt: Boolean): Unit = { + fullOpt: Boolean, + moduleKind: ModuleKind): Unit = { bridge(toolsClasspath).link( sources.items.map(_.toIO).toArray, libraries.items.map(_.toIO).toArray, dest, main.orNull, - fullOpt + fullOpt, + moduleKind ) } @@ -68,7 +76,8 @@ trait ScalaJSBridge { libraries: Array[File], dest: File, main: String, - fullOpt: Boolean): Unit + fullOpt: Boolean, + moduleKind: ModuleKind): Unit def run(config: NodeJSConfig, linkedFile: File): Unit diff --git a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala index 948b13df..92c071c2 100644 --- a/scalajslib/src/mill/scalajslib/ScalaJSModule.scala +++ b/scalajslib/src/mill/scalajslib/ScalaJSModule.scala @@ -72,7 +72,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => toolsClasspath(), runClasspath(), finalMainClassOpt().toOption, - FastOpt + FastOpt, + moduleKind() ) } @@ -82,7 +83,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => toolsClasspath(), runClasspath(), finalMainClassOpt().toOption, - FullOpt + FullOpt, + moduleKind() ) } @@ -114,7 +116,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => toolsClasspath: Agg[PathRef], runClasspath: Agg[PathRef], mainClass: Option[String], - mode: OptimizeMode)(implicit ctx: Ctx.Dest): PathRef = { + mode: OptimizeMode, + moduleKind: ModuleKind)(implicit ctx: Ctx.Dest): PathRef = { val outputPath = ctx.dest / "out.js" mkdir(ctx.dest) @@ -132,7 +135,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => libraries, outputPath.toIO, mainClass, - mode == FullOpt + mode == FullOpt, + moduleKind ) PathRef(outputPath) } @@ -159,6 +163,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer => override def platformSuffix = s"_sjs${artifactScalaJSVersion()}" def nodeJSConfig = T { NodeJSConfig() } + + def moduleKind: T[ModuleKind] = T { ModuleKind.NoModule } } trait TestScalaJSModule extends ScalaJSModule with TestModule { @@ -177,7 +183,8 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule { toolsClasspath(), scalaJSTestDeps() ++ runClasspath(), None, - FastOpt + FastOpt, + moduleKind() ) } diff --git a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala index 2429a189..cfdcdd1f 100644 --- a/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala +++ b/scalajslib/test/src/mill/scalajslib/HelloJSWorldTests.scala @@ -102,7 +102,7 @@ object HelloJSWorldTests extends TestSuite { 'fromScratch_2124_0622 - testCompileFromScratch("2.12.4", "0.6.22") 'fromScratch_2123_0622 - testCompileFromScratch("2.12.3", "0.6.22") - 'fromScratch_2118_0622 - testCompileFromScratch("2.11.8", "0.6.22") + 'fromScratch_2118_0622 - TestUtil.disableInJava9OrAbove(testCompileFromScratch("2.11.8", "0.6.22")) 'fromScratch_2124_100M2 - testCompileFromScratch("2.12.4", "1.0.0-M2") } @@ -119,16 +119,16 @@ object HelloJSWorldTests extends TestSuite { } 'fullOpt - { - 'run_2124_0622 - testRun("2.12.4", "0.6.22", FullOpt) - 'run_2123_0622 - testRun("2.12.3", "0.6.22", FullOpt) - 'run_2118_0622 - testRun("2.11.8", "0.6.22", FullOpt) - 'run_2124_100M2 - testRun("2.12.4", "1.0.0-M2", FullOpt) + 'run_2124_0622 - TestUtil.disableInJava9OrAbove(testRun("2.12.4", "0.6.22", FullOpt)) + 'run_2123_0622 - TestUtil.disableInJava9OrAbove(testRun("2.12.3", "0.6.22", FullOpt)) + 'run_2118_0622 - TestUtil.disableInJava9OrAbove(testRun("2.11.8", "0.6.22", FullOpt)) + 'run_2124_100M2 - TestUtil.disableInJava9OrAbove(testRun("2.12.4", "1.0.0-M2", FullOpt)) } 'fastOpt - { - 'run_2124_0622 - testRun("2.12.4", "0.6.22", FastOpt) - 'run_2123_0622 - testRun("2.12.3", "0.6.22", FastOpt) - 'run_2118_0622 - testRun("2.11.8", "0.6.22", FastOpt) - 'run_2124_100M2 - testRun("2.12.4", "1.0.0-M2", FastOpt) + 'run_2124_0622 - TestUtil.disableInJava9OrAbove(testRun("2.12.4", "0.6.22", FastOpt)) + 'run_2123_0622 - TestUtil.disableInJava9OrAbove(testRun("2.12.3", "0.6.22", FastOpt)) + 'run_2118_0622 - TestUtil.disableInJava9OrAbove(testRun("2.11.8", "0.6.22", FastOpt)) + 'run_2124_100M2 - TestUtil.disableInJava9OrAbove(testRun("2.12.4", "1.0.0-M2", FastOpt)) } 'jar - { 'containsSJSIRs - { @@ -192,12 +192,12 @@ object HelloJSWorldTests extends TestSuite { ) } - 'utest_2118_0622 - checkUtest("2.11.8", "0.6.22") + 'utest_2118_0622 - TestUtil.disableInJava9OrAbove(checkUtest("2.11.8", "0.6.22")) 'utest_2124_0622 - checkUtest("2.12.4", "0.6.22") - 'utest_2118_100M2 - checkUtest("2.11.8", "1.0.0-M2") + 'utest_2118_100M2 - TestUtil.disableInJava9OrAbove(checkUtest("2.11.8", "1.0.0-M2")) 'utest_2124_100M2 - checkUtest("2.12.4", "1.0.0-M2") - 'scalaTest_2118_0622 - checkScalaTest("2.11.8", "0.6.22") + 'scalaTest_2118_0622 - TestUtil.disableInJava9OrAbove(checkScalaTest("2.11.8", "0.6.22")) 'scalaTest_2124_0622 - checkScalaTest("2.12.4", "0.6.22") // No scalatest artifact for scala.js 1.0.0-M2 published yet // 'scalaTest_2118_100M2 - checkScalaTest("2.11.8", "1.0.0-M2") @@ -222,9 +222,9 @@ object HelloJSWorldTests extends TestSuite { } 'run - { - 'run_2118_0622 - checkRun("2.11.8", "0.6.22") + 'run_2118_0622 - TestUtil.disableInJava9OrAbove(checkRun("2.11.8", "0.6.22")) 'run_2124_0622 - checkRun("2.12.4", "0.6.22") - 'run_2118_100M2 - checkRun("2.11.8", "1.0.0-M2") + 'run_2118_100M2 - TestUtil.disableInJava9OrAbove(checkRun("2.11.8", "1.0.0-M2")) 'run_2124_100M2 - checkRun("2.12.4", "1.0.0-M2") } } diff --git a/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala b/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala index e2364f38..37429038 100644 --- a/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala +++ b/scalajslib/test/src/mill/scalajslib/MultiModuleTests.scala @@ -54,8 +54,8 @@ object MultiModuleTests extends TestSuite { ) } - 'fastOpt - checkOpt(FastOpt) - 'fullOpt - checkOpt(FullOpt) + 'fastOpt - TestUtil.disableInJava9OrAbove(checkOpt(FastOpt)) + 'fullOpt - TestUtil.disableInJava9OrAbove(checkOpt(FullOpt)) 'test - { val Right(((_, testResults), evalCount)) = evaluator(MultiModule.client.test.test()) diff --git a/scalalib/src/mill/scalalib/ScalaModule.scala b/scalalib/src/mill/scalalib/ScalaModule.scala index 5a355bc6..c06fb8f3 100644 --- a/scalalib/src/mill/scalalib/ScalaModule.scala +++ b/scalalib/src/mill/scalalib/ScalaModule.scala @@ -71,6 +71,7 @@ trait ScalaModule extends mill.Module with TaskModule { outer => def transitiveIvyDeps: T[Agg[Dep]] = T{ ivyDeps() ++ Task.traverse(moduleDeps)(_.transitiveIvyDeps)().flatten } + def upstreamCompileOutput = T{ Task.traverse(moduleDeps)(_.compile) } @@ -247,6 +248,20 @@ trait ScalaModule extends mill.Module with TaskModule { outer => ) } + def ivyDepsTree(inverse: Boolean = false) = T.command { + import coursier.{Cache, Fetch, Resolution} + + val flattened = ivyDeps().map(depToDependency(_, scalaVersion(), platformSuffix())).toSeq + val start = Resolution(flattened.toSet) + val fetch = Fetch.from(repositories, Cache.fetch()) + val resolution = start.process.run(fetch).unsafePerformSync + + println(coursier.util.Print.dependencyTree(flattened, resolution, + printExclusions = false, reverse = inverse)) + + Result.Success() + } + def runLocal(args: String*) = T.command { Jvm.runLocal( finalMainClass(), @@ -301,7 +316,7 @@ trait ScalaModule extends mill.Module with TaskModule { outer => } def ammoniteReplClasspath = T{ - resolveDeps(T.task{Agg(ivy"com.lihaoyi:::ammonite:1.0.3")})() + resolveDeps(T.task{Agg(ivy"com.lihaoyi:::ammonite:1.0.5-4-c0cdbaf")})() } def repl() = T.command{ if (T.ctx().log.inStream == DummyInputStream){ diff --git a/scalalib/src/mill/scalalib/ScalaWorkerApi.scala b/scalalib/src/mill/scalalib/ScalaWorkerApi.scala index 2d04ac4e..91222524 100644 --- a/scalalib/src/mill/scalalib/ScalaWorkerApi.scala +++ b/scalalib/src/mill/scalalib/ScalaWorkerApi.scala @@ -31,8 +31,8 @@ trait ScalaWorkerModule extends mill.Module{ } } def worker: Worker[ScalaWorkerApi] = T.worker{ - val cl = new java.net.URLClassLoader( - classpath().map(_.toNIO.toUri.toURL).toArray, + val cl = mill.util.ClassLoader.create( + classpath().map(_.toNIO.toUri.toURL).toVector, getClass.getClassLoader ) val cls = cl.loadClass("mill.scalaworker.ScalaWorker") diff --git a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala index 317f9bec..61d2b724 100644 --- a/scalalib/test/src/mill/scalalib/HelloWorldTests.scala +++ b/scalalib/test/src/mill/scalalib/HelloWorldTests.scala @@ -246,8 +246,8 @@ object HelloWorldTests extends TestSuite { read(runResult) == expectedOut ) } - 'v210 - workspaceTest(CrossHelloWorld)(cross(_, "2.10.6", "2.10.6 rox")) - 'v211 - workspaceTest(CrossHelloWorld)(cross(_, "2.11.11", "2.11.11 pwns")) + 'v210 - TestUtil.disableInJava9OrAbove(workspaceTest(CrossHelloWorld)(cross(_, "2.10.6", "2.10.6 rox"))) + 'v211 - TestUtil.disableInJava9OrAbove(workspaceTest(CrossHelloWorld)(cross(_, "2.11.11", "2.11.11 pwns"))) 'v2123 - workspaceTest(CrossHelloWorld)(cross(_, "2.12.3", "2.12.3 leet")) 'v2124 - workspaceTest(CrossHelloWorld)(cross(_, "2.12.4", "2.12.4 leet")) } diff --git a/scalaworker/src/mill/scalaworker/ScalaWorker.scala b/scalaworker/src/mill/scalaworker/ScalaWorker.scala index 12511b60..ca20ccf1 100644 --- a/scalaworker/src/mill/scalaworker/ScalaWorker.scala +++ b/scalaworker/src/mill/scalaworker/ScalaWorker.scala @@ -89,7 +89,7 @@ class ScalaWorker(ctx0: mill.util.Ctx, .get val sourceFolder = mill.modules.Util.unpackZip(sourceJar)(workingDir) - val classloader = new URLClassLoader(compilerJars.map(_.toURI.toURL), null) + val classloader = mill.util.ClassLoader.create(compilerJars.map(_.toURI.toURL), null) val scalacMain = classloader.loadClass("scala.tools.nsc.Main") val argsArray = Array[String]( "-d", compiledDest.toString, @@ -145,7 +145,7 @@ class ScalaWorker(ctx0: mill.util.Ctx, val compilerClassLoader = scalaClassloaderCache match{ case Some((k, v)) if k == compilerClassloaderSig => v case _ => - val classloader = new URLClassLoader(compilerJars.map(_.toURI.toURL), null) + val classloader = mill.util.ClassLoader.create(compilerJars.map(_.toURI.toURL), null) scalaClassloaderCache = Some((compilerClassloaderSig, classloader)) classloader } @@ -155,7 +155,7 @@ class ScalaWorker(ctx0: mill.util.Ctx, case _ => val scalaInstance = new ScalaInstance( version = scalaVersion, - loader = new URLClassLoader(pluginJars.map(_.toURI.toURL), compilerClassLoader), + loader = mill.util.ClassLoader.create(pluginJars.map(_.toURI.toURL), compilerClassLoader), libraryJar = grepJar(compilerClasspath, s"scala-library-$scalaVersion.jar"), compilerJar = grepJar(compilerClasspath, s"scala-compiler-$scalaVersion.jar"), allJars = compilerJars ++ pluginJars, @@ -333,8 +333,8 @@ class ScalaWorker(ctx0: mill.util.Ctx, val cls = cl.loadClass(path.stripSuffix(".class").replace('/', '.')) fingerprints.find { case f: SubclassFingerprint => - - (f.isModule == cls.getName.endsWith("$")) && + !cls.isInterface && + (f.isModule == cls.getName.endsWith("$")) && cl.loadClass(f.superclassName()).isAssignableFrom(cls) case f: AnnotatedFingerprint => (f.isModule == cls.getName.endsWith("$")) && |