Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: com-lihaoyi/mill
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.10.4
Choose a base ref
...
head repository: com-lihaoyi/mill
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.10.5
Choose a head ref

Commits on May 6, 2022

  1. Update mill-main to 0.10.4 (#1867)

    Pull request: #1867
    scala-steward authored May 6, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    16feb60 View commit details

Commits on May 7, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8981d42 View commit details

Commits on May 10, 2022

  1. Enable ScalaJS optimizer by default (#1869)

    Introduce `scalaJSOptimizer: T[Boolean] = true` target
    to make it configurable.
    Set the default to `true` since it is what ScalaJS suggests and
    uses in the official Sbt plugin.
    
    Pull request: #1869
    lolgab authored May 10, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    034711a View commit details
  2. Add Junit5 TestModule (#1861)

    Pull request: #1861
    
    Co-authored-by: Tobias Roeser <le.petit.fou@web.de>
    sake92 and lefou authored May 10, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4d182c9 View commit details

Commits on May 11, 2022

  1. Fix universal-main args handling (#1871)

    Pull request: #1871
    sake92 authored May 11, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d623fd1 View commit details

Commits on May 12, 2022

  1. Fix visualize command (#1872)

    Fixes #1652
    
    1. use graphviz-java-all-j2v8 instead of graphviz-java (now as transitive dependency)
    Following instructions from graphviz-java [docs](https://github.com/nidi3/graphviz-java#maven
    ) they say:
    > gradle does not support this way of defining a dependency
    > Instead of graphviz-java there are two alternative dependencies that can be used:
    > - graphviz-java-all-j2v8 additionally contains dependencies to all J2V8 platforms. So the same application can run on Linux, Mac OS X and Windows.
    > - graphviz-java-min-deps contains only dependencies that are absolutely necessary. All other dependencies are marked as optional and must added manually. See the [pom.xml](https://github.com/nidi3/graphviz-java/blob/master/graphviz-java-min-deps/pom.xml#L64-L90) for details.
    
    2. downgrade jgrapht since 1.5.0+ dont support JDK8
    https://github.com/jgrapht/jgrapht#dependencies
    
    This adds around 3MB of extra dependencies.  
    The upside is that it works on all JDK: 8, 11 and 17! (tested locally on win10)
    
    Pull request: #1872
    sake92 authored May 12, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3f18d00 View commit details

Commits on May 15, 2022

  1. Copy the full SHA
    a8f69e0 View commit details

Commits on May 17, 2022

  1. BSP: Fix mill-build module interpretation in IntelliJ IDEA (#1876)

    IntelliJ IDEA does not understand single files as sources, which we would need to handle `build.sc`. But when we use the project root directory, it creates a problem where IntelliJ may interpret a `root.Foo` class in a sub-project `sub/foo` as `sub.foo.src.root.Foo` class.
    
    Pull request: #1876
    atty303 authored May 17, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0fd40b0 View commit details
  2. Handle FileSystemException when creating an input stream (#1878)

    When creating a `PathRef` of a path that contains socket files, which is for example the case if the path contains the `out` directory of Mill, Mill is failing because it can't read the socket file to calculate the content digest. We already skip digesting of unreadable files but somehow those socket files are not marked as unreadable. There is no performant and platform neutral way to detect socket files, so this PR just catches the typical `FileSystemException` at `InputStream` creation time and gracefully handles it (like other unreadable files) by just ignoring its content.
    
    * Fix #1875
    * Fix #823
    
    Pull request: #1878
    lefou authored May 17, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bc44610 View commit details

Commits on May 18, 2022

  1. Update coursier to 2.1.0-M6 (#1881)

    Pull request: #1881
    scala-steward authored May 18, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fa63e50 View commit details

Commits on May 19, 2022

  1. Update trees to 4.5.7 (#1882)

    Pull request: #1882
    scala-steward authored May 19, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4d94945 View commit details

Commits on May 20, 2022

  1. Copy the full SHA
    7c464a3 View commit details

Commits on May 21, 2022

  1. Address PR comments

    sake92 committed May 21, 2022
    Copy the full SHA
    b246c56 View commit details

Commits on May 23, 2022

  1. Add Giter8 basic test

    sake92 committed May 23, 2022
    Copy the full SHA
    2ca0541 View commit details
  2. Copy the full SHA
    61f8c09 View commit details

Commits on May 24, 2022

  1. Reworked giter8 test

    lefou committed May 24, 2022

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    lefou Tobias Roeser
    Copy the full SHA
    a259c9d View commit details
  2. Merge pull request #1 from lefou/mill-new-project-command

    Reworked giter8 test
    sake92 authored May 24, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    27f3888 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e8ef33d View commit details
  4. Update trees to 4.5.8 (#1885)

    Pull request: #1885
    scala-steward authored May 24, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a7252b2 View commit details

Commits on May 30, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c5128bc View commit details
  2. Fix lunr-extension version (#1889)

    Pull request: #1889
    sake92 authored May 30, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2b9e71c View commit details

Commits on May 31, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1a2fbde View commit details

Commits on Jun 3, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    eb6204d View commit details

Commits on Jun 7, 2022

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6faca06 View commit details

Commits on Jun 8, 2022

  1. Support Scala Native nativeEmbedResources (#1890)

    This adds support for `nativeEmbedResources` (available in Scala Native 0.4.4+)
    Since we support Scala Native 0.4.0+ this uses the same mechanism `scalajslib` uses to execute methods only on versions a certain feature is available.
    
    Pull request: #1890
    lolgab authored Jun 8, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8119ca5 View commit details

Commits on Jun 12, 2022

  1. Fixed links to examples in documentation (#1898)

    Fixes #1897
    
    Pull request: #1898
    lefou authored Jun 12, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    160b658 View commit details

Commits on Jun 23, 2022

  1. Fixed ordering-sensitive test (#1905)

    We saw CI failures lately in this specific test.
    
    As test cases are picked up from class files which order may depend on the used filesystem and other factors like creation time, inode number, ..., we better always try to avoid any ordering assumptions in tests.
    lefou authored Jun 23, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    12e0775 View commit details
  2. Removed Better-Files integration tests (#1906)

    They where only working on very limited platforms (Java 8 on Linux) and even then produced flaky results.
    
    Pull request: #1906
    lefou authored Jun 23, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e50fa4a View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d5d7dfc View commit details

Commits on Jun 24, 2022

  1. Fix zinc binary dependencies (#1904)

    Fix #1901
    
    Zinc uses a `MappedFileConverter`, it will converter `jdk` internal classes like `/module/java.base/java.lang.String` associated with a dummpy `rt.jar`.
    https://github.com/sbt/zinc/blob/57d03412abe3810be5762a8c8e8c55cbf622ed03/internal/zinc-core/src/main/scala/sbt/internal/inc/MappedVirtualFile.scala#L56
    
    ```scala
    def toVirtualFile(path: Path): VirtualFile = {
        rootPaths2.find { case (_, rootPath) => path.startsWith(rootPath) } match {
          case Some((key, rootPath)) =>
            MappedVirtualFile(s"$${$key}/${rootPath.relativize(path)}".replace('\\', '/'), rootPaths)
          case _ =>
            def isCtSym =
              path.getFileSystem
                .provider()
                .getScheme == "jar" && path.getFileSystem.toString.endsWith("ct.sym")
            def isJrt = path.getFileSystem.provider().getScheme == "jrt"
            if (isJrt || path.getFileName.toString == "rt.jar" || isCtSym)
              DummyVirtualFile("rt.jar", path)
            else if (allowMachinePath) MappedVirtualFile(s"$path".replace('\\', '/'), rootPaths)
            else sys.error(s"$path cannot be mapped using the root paths $rootPaths")
        }
      }
    ```
    
    And later the `Incremental`  will exclude such binary dependencies.
    https://github.com/sbt/zinc/blob/57d03412abe3810be5762a8c8e8c55cbf622ed03/internal/zinc-core/src/main/scala/sbt/internal/inc/Incremental.scala#L783
    
    ```scala
    
            // dependency is some other binary on the classpath.
            // exclude dependency tracking with rt.jar, for example java.lang.String -> rt.jar.
            if (!vf.id.endsWith("rt.jar")) {
              externalLibraryDependency(
                vf,
                onBinaryName,
                sourceFile,
                context
              )
            }
    ```
    
    This commit implements the exclusion, when reading the `Incremental` analysis file.
    
    Pull request: #1904
    jilen authored Jun 24, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    42d72a6 View commit details
  2. Test case ensuring zinc is only re-compiling changed sources (#1907)

    Regression test, making sure Zinc incremental compilation only compile changed files.
    
    Related to
    
    * #1901
    * #1904
    
    Pull request: #1907
    lefou authored Jun 24, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    00bd25d View commit details

Commits on Jun 29, 2022

  1. Added a link to JProfile website

    They provided us a free license for JProfiler 13.x
    lefou authored Jun 29, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ef24824 View commit details

Commits on Jul 1, 2022

  1. Update bloop-config to 1.5.2 (#1909)

    Pull request: #1909
    lefou authored Jul 1, 2022

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f47c455 View commit details
  2. Prepared release 0.10.5

    lefou committed Jul 1, 2022

    Verified

    This commit was signed with the committer’s verified signature. The key has expired.
    lefou Tobias Roeser
    Copy the full SHA
    77ca92b View commit details
Showing with 533 additions and 249 deletions.
  1. +1 −1 .mill-version
  2. +15 −0 bsp/src/mill/bsp/MillBuildServer.scala
  3. +14 −19 build.sc
  4. +3 −3 docs/antora/antora.yml
  5. +8 −18 docs/antora/modules/ROOT/pages/Common_Project_Layouts.adoc
  6. +2 −1 docs/antora/modules/ROOT/pages/Configuring_Mill.adoc
  7. +7 −0 docs/antora/modules/ROOT/pages/Thirdparty_Plugins.adoc
  8. +1 −0 integration/forked-server/src/forked-server-tests.scala
  9. +1 −0 integration/forked/src/forked-tests.scala
  10. +20 −0 integration/local/resources/zinc-incremental-compilation/app/src/main/scala/App.scala
  11. +8 −0 integration/local/resources/zinc-incremental-compilation/app/src/main/scala/models/TestModel1.scala
  12. +14 −0 integration/local/resources/zinc-incremental-compilation/build.sc
  13. +42 −0 integration/local/src/ZincIncrementalCompilationTests.scala
  14. +6 −5 integration/local/src/local/local-tests.scala
  15. +0 −1 integration/thirdparty/forked/src/Tests.scala
  16. +0 −86 integration/thirdparty/local/resources/better-files/build.sc
  17. +0 −32 integration/thirdparty/local/src/BetterFilesTests.scala
  18. +0 −1 integration/thirdparty/local/src/local/Tests.scala
  19. +16 −3 main/api/src/mill/api/PathRef.scala
  20. +1 −1 main/client/src/mill/main/client/MillClientMain.java
  21. +3 −4 main/src/mill/MillConfig.scala
  22. +8 −0 main/src/mill/main/MainModule.scala
  23. +0 −6 main/test/src/main/ClientServerTests.scala
  24. +36 −2 readme.adoc
  25. +19 −11 scalajslib/src/mill/scalajslib/ScalaJSModule.scala
  26. +2 −1 scalajslib/src/mill/scalajslib/ScalaJSWorkerApi.scala
  27. +4 −2 scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala
  28. +2 −1 scalajslib/worker-api/src/ScalaJSWorkerApi.scala
  29. +19 −10 scalajslib/worker/0.6/src/ScalaJSWorkerImpl.scala
  30. +14 −11 scalajslib/worker/1/src/ScalaJSWorkerImpl.scala
  31. +11 −0 scalalib/src/TestModule.scala
  32. +33 −0 scalalib/src/giter8/Giter8Module.scala
  33. +3 −0 scalalib/src/mill/scalalib/bsp/BspModule.scala
  34. +5 −0 scalalib/test/resources/giter8/hello.g8/src/main/g8/$name__camel$/src/Hello.scala
  35. +9 −0 scalalib/test/resources/giter8/hello.g8/src/main/g8/$name__camel$/test/src/MyTest.scala
  36. +6 −0 scalalib/test/resources/giter8/hello.g8/src/main/g8/.gitignore
  37. +17 −0 scalalib/test/resources/giter8/hello.g8/src/main/g8/README.md
  38. +12 −0 scalalib/test/resources/giter8/hello.g8/src/main/g8/build.sc
  39. +2 −0 scalalib/test/resources/giter8/hello.g8/src/main/g8/default.properties
  40. +2 −0 scalalib/test/resources/hello-java/app/testJunit5/resources/junit-platform.properties
  41. +41 −0 scalalib/test/resources/hello-java/app/testJunit5/src/Junit5TestsA.java
  42. +18 −0 scalalib/test/src/HelloJavaTests.scala
  43. +50 −0 scalalib/test/src/giter8/Giter8Tests.scala
  44. +5 −2 scalalib/worker/src/mill/scalalib/worker/MockedLookup.scala
  45. +2 −1 scalalib/worker/src/mill/scalalib/worker/ZincWorkerImpl.scala
  46. +2 −0 scalanativelib/api/src/mill/scalanativelib/api/ScalaNativeWorkerApi.java
  47. +10 −1 scalanativelib/src/ScalaNativeModule.scala
  48. +29 −19 scalanativelib/worker/0.4/src/ScalaNativeWorkerImpl.scala
  49. +10 −7 testrunner/src/TestRunner.scala
2 changes: 1 addition & 1 deletion .mill-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.10.3
0.10.4
15 changes: 15 additions & 0 deletions bsp/src/mill/bsp/MillBuildServer.scala
Original file line number Diff line number Diff line change
@@ -89,6 +89,7 @@ class MillBuildServer(
var clientInitialized = false
var shutdownRequested = false
var clientWantsSemanticDb = false
var clientIsIntelliJ = false

class State(val evaluator: Evaluator) {
private[this] object internal {
@@ -221,6 +222,11 @@ class MillBuildServer(
capabilities.setJvmRunEnvironmentProvider(true)
capabilities.setJvmTestEnvironmentProvider(true)

request.getDisplayName match {
case "IntelliJ-BSP" => clientIsIntelliJ = true
case _ => clientIsIntelliJ = false
}

request.getData match {
case d: JsonObject =>
log.debug(s"extra data: ${d} of type ${d.getClass}")
@@ -335,6 +341,15 @@ class MillBuildServer(
targetIds = sourcesParams.getTargets.asScala.toSeq,
agg = (items: Seq[SourcesItem]) => new SourcesResult(items.asJava)
) {
case (id, module: MillBuildTarget) if clientIsIntelliJ =>
T.task {
val sources = new SourcesItem(
id,
module.dummySources().map(p => sourceItem(p.path, true)).asJava
)
sources.setRoots(Seq(sanitizeUri(evaluator.rootModule.millSourcePath)).asJava)
sources
}
// case (id, `millBuildTarget`) =>
// T.task {
// new SourcesItem(
33 changes: 14 additions & 19 deletions build.sc
Original file line number Diff line number Diff line change
@@ -43,9 +43,10 @@ object Settings {
"0.10.1",
"0.10.2",
"0.10.3",
"0.10.4"
"0.10.4",
"0.10.5"
)
val mimaBaseVersions = Seq("0.10.0")
val mimaBaseVersions = Seq("0.10.0", "0.10.1", "0.10.2", "0.10.3", "0.10.4")
}

object Deps {
@@ -83,7 +84,7 @@ object Deps {
}

val acyclic = ivy"com.lihaoyi::acyclic:0.2.1"
val ammoniteVersion = "2.5.3"
val ammoniteVersion = "2.5.4"
val ammonite = ivy"com.lihaoyi:::ammonite:${ammoniteVersion}"
val ammoniteTerminal = ivy"com.lihaoyi::ammonite-terminal:${ammoniteVersion}"
// Exclude trees here to force the version of we have defined. We use this
@@ -93,20 +94,20 @@ object Deps {
"org.scalameta" -> "trees_2.13"
)
val asciidoctorj = ivy"org.asciidoctor:asciidoctorj:2.4.3"
val bloopConfig = ivy"ch.epfl.scala::bloop-config:1.5.0"
val coursier = ivy"io.get-coursier::coursier:2.1.0-M5"
val bloopConfig = ivy"ch.epfl.scala::bloop-config:1.5.2"
val coursier = ivy"io.get-coursier::coursier:2.1.0-M6"

val flywayCore = ivy"org.flywaydb:flyway-core:8.0.2"
val graphvizJava = ivy"guru.nidi:graphviz-java:0.18.1"
val junixsocket = ivy"com.kohlschutter.junixsocket:junixsocket-core:2.4.0"
val graphvizJava = ivy"guru.nidi:graphviz-java-all-j2v8:0.18.1"
val junixsocket = ivy"com.kohlschutter.junixsocket:junixsocket-core:2.5.0"

object jetty {
val version = "8.2.0.v20160908"
val server = ivy"org.eclipse.jetty:jetty-server:${version}"
val websocket = ivy"org.eclipse.jetty:jetty-websocket:${version}"
}
val javaxServlet = ivy"org.eclipse.jetty.orbit:javax.servlet:3.0.0.v201112011016"
val jgraphtCore = ivy"org.jgrapht:jgrapht-core:1.5.1"
val jgraphtCore = ivy"org.jgrapht:jgrapht-core:1.4.0" // 1.5.0+ dont support JDK8

val jna = ivy"net.java.dev.jna:jna:5.11.0"
val jnaPlatform = ivy"net.java.dev.jna:jna-platform:5.11.0"
@@ -120,11 +121,11 @@ object Deps {
val scalaCheck = ivy"org.scalacheck::scalacheck:1.16.0"
def scalaCompiler(scalaVersion: String) = ivy"org.scala-lang:scala-compiler:${scalaVersion}"
val scalafmtDynamic = ivy"org.scalameta::scalafmt-dynamic:3.4.3"
val scalametaTrees = ivy"org.scalameta::trees:4.5.6"
val scalametaTrees = ivy"org.scalameta::trees:4.5.8"
def scalaReflect(scalaVersion: String) = ivy"org.scala-lang:scala-reflect:${scalaVersion}"
def scalacScoveragePlugin = ivy"org.scoverage:::scalac-scoverage-plugin:1.4.11"
val sourcecode = ivy"com.lihaoyi::sourcecode:0.2.8"
val upickle = ivy"com.lihaoyi::upickle:1.6.0"
val upickle = ivy"com.lihaoyi::upickle:2.0.0"
val utest = ivy"com.lihaoyi::utest:0.7.11"
val windowsAnsi = ivy"io.github.alexarchambault.windows-ansi:windows-ansi:0.0.3"
val zinc = ivy"org.scala-sbt::zinc:1.6.1"
@@ -928,12 +929,6 @@ object integration extends MillScalaModule {
"fd8dc2b41ce70269889320aeabf8614fe1e8fbcb",
T.dest / "jawn"
),
"MILL_BETTERFILES_REPO" ->
shared.downloadTestRepo(
"pathikrit/better-files",
"ba74ae9ef784dcf37f1b22c3990037a4fcc6b5f8",
T.dest / "better-files"
),
"MILL_AMMONITE_REPO" ->
shared.downloadTestRepo(
"lihaoyi/ammonite",
@@ -1201,10 +1196,10 @@ object docs extends Module {
commandArgs = Seq(
npmExe,
"install",
"@antora/cli",
"@antora/site-generator-default",
"@antora/cli@3.0.1",
"@antora/site-generator-default@3.0.1",
"gitlab:antora/xref-validator",
"@antora/lunr-extension"
"@antora/lunr-extension@v1.0.0-alpha.6"
),
envArgs = Map(),
workingDir = npmDir
6 changes: 3 additions & 3 deletions docs/antora/antora.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: mill
title: Mill Documentation
version: '0.10.4'
version: '0.10.5'
nav:
- modules/ROOT/nav.adoc
asciidoc:
attributes:
mill-version: '0.10.4'
mill-last-tag: '0.10.4'
mill-version: '0.10.5'
mill-last-tag: '0.10.5'
bsp-version: '2.0.0'
example-semanticdb-version: '4.4.32'
example-scala-version: '2.13.8'
26 changes: 8 additions & 18 deletions docs/antora/modules/ROOT/pages/Common_Project_Layouts.adoc
Original file line number Diff line number Diff line change
@@ -10,11 +10,11 @@ Scala build:
[source,scala]
----
object core extends JavaModule {
object test extends Tests with TestModule.Junit
object test extends Tests with TestModule.Junit4
}
object app extends JavaModule {
def moduleDeps = Seq(core)
object test extends Tests with TestModule.Junit
object test extends Tests with TestModule.Junit4
}
----

@@ -40,11 +40,10 @@ You can then run the junit tests using `mill app.test` or `mill core.test`, and
configure which exact tests you want to run using the flags defined on the
https://github.com/sbt/junit-interface#junit-interface[JUnit Test Interface].

For a more more complex, real-world example of a Java build, check out our
example build for the popular https://github.com/ben-manes/caffeine[Caffeine]
For a more more complex, real-world example of a Java build, check out our example build for the popular https://github.com/ben-manes/caffeine[Caffeine]
project:

* https://github.com/com-lihaoyi/mill/blob/main/integration/test/resources/caffeine/build.sc[Example Build]
* {mill-github-url}/blob/main/integration/thirdparty/local/resources/caffeine/build.sc[Example Build]

== Cross Scala-Version Modules

@@ -376,37 +375,28 @@ integration tests and examples:

=== Acyclic

* {mill-github-url}/blob/main/integration/test/resources/acyclic/build.sc#L1[Mill Build]
* {mill-github-url}/blob/main/integration/thirdparty/local/resources/acyclic/build.sc#L1[Mill Build]

A small single-module cross-build, with few sources, minimal dependencies, and
wired up for publishing to Maven Central.

=== Better-Files

* {mill-github-url}/blob/main/integration/test/resources/better-files/build.sc#L1[Mill Build]

A collection of small modules compiled for a single Scala version.

Also demonstrates how to define shared configuration in a `trait`, enable Scala
compiler flags, and download artifacts as part of the build.

=== Jawn

* {mill-github-url}/blob/main/integration/test/resources/jawn/build.sc#L1[Mill Build]
* {mill-github-url}/blob/main/integration/thirdparty/local/resources/jawn/build.sc#L1[Mill Build]

A collection of relatively small modules, all cross-built across the same few
versions of Scala.

=== Upickle

* {mill-github-url}/blob/main/integration/test/resources/upickle/build.sc#L1[Mill Build]
* {mill-github-url}/blob/main/integration/thirdparty/local/resources/upickle/build.sc#L1[Mill Build]

A single cross-platform Scala.js/Scala-JVM module cross-built against multiple
versions of Scala, including the setup necessary for publishing to Maven Central.

=== Ammonite

* {mill-github-url}/blob/main/integration/test/resources/ammonite/build.sc#L1[Mill Build]
* {mill-github-url}/blob/main/integration/thirdparty/local/resources/ammonite/build.sc#L1[Mill Build]

A relatively complex build with numerous submodules, some cross-built across
Scala major versions while others are cross-built against Scala minor versions.
3 changes: 2 additions & 1 deletion docs/antora/modules/ROOT/pages/Configuring_Mill.adoc
Original file line number Diff line number Diff line change
@@ -180,7 +180,8 @@ object foo extends ScalaModule {

For convenience, you can also use one of the predefined test frameworks:

* `TestModule.Junit`
* `TestModule.Junit4`
* `TestModule.Junit5`
* `TestModule.TestNg`
* `TestModule.Munit`
* `TestModule.ScalaTest`
7 changes: 7 additions & 0 deletions docs/antora/modules/ROOT/pages/Thirdparty_Plugins.adoc
Original file line number Diff line number Diff line change
@@ -535,6 +535,13 @@ object project extends ScalaModule with OsgiBundleModule {
}
----

== PowerShell Completion

Basic PowerShell completion support.

Project home: https://github.com/sake92/mill-powershell-completion


== PublishM2

_Since Mill `0.6.1-27-f265a4` there is a built-in `publishM2Local` target in `PublishModule`._
1 change: 1 addition & 0 deletions integration/forked-server/src/forked-server-tests.scala
Original file line number Diff line number Diff line change
@@ -6,3 +6,4 @@ object HygieneTests extends HygieneTests(fork = true, clientServer = true)
object LargeProjectTests extends LargeProjectTests(fork = true, clientServer = true)
object ScriptsInvalidationTests extends ScriptsInvalidationTests(fork = true, clientServer = true)
object ScriptsInvalidationForeignTests extends ScriptsInvalidationForeignTests(fork = true, clientServer = true)
object ZincIncrementalCompilationTests extends ZincIncrementalCompilationTests(fork = true, clientServer = true)
1 change: 1 addition & 0 deletions integration/forked/src/forked-tests.scala
Original file line number Diff line number Diff line change
@@ -6,3 +6,4 @@ object HygieneTests extends HygieneTests(fork = true, clientServer = false)
object LargeProjectTests extends LargeProjectTests(fork = true, clientServer = false)
object ScriptsInvalidationTests extends ScriptsInvalidationTests(fork = true, clientServer = false)
object ScriptsInvalidationForeignTests extends ScriptsInvalidationForeignTests(fork = true, clientServer = false)
object ZincIncrementalCompilationTests extends ZincIncrementalCompilationTests(fork = true, clientServer = false)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package app

import io.getquill._

object App {

val ctx = new SqlMirrorContext(PostgresDialect, SnakeCase)
import ctx._

case class Person(name: String, age: Int)

def test = {
val key = "foo"
val q = quote {
query[Person].filter(c => c.name like "% $1" + lift(key) + "%")
}
ctx.run(q)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package models

import java.time._

case class Foo(
id: Long = 0L,
gmtCreate: LocalDateTime
)
14 changes: 14 additions & 0 deletions integration/local/resources/zinc-incremental-compilation/build.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Issue https://github.com/com-lihaoyi/mill/issues/1901
import mill._
import mill.scalalib._

object app extends SbtModule {

def scalaVersion = "2.13.8"

def scalacOptions = Seq("-Vclasspath")

def ivyDeps = Agg(
ivy"io.getquill::quill-sql:3.18.0"
)
}
42 changes: 42 additions & 0 deletions integration/local/src/ZincIncrementalCompilationTests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mill.integration

import utest._

// Regress test for issue https://github.com/com-lihaoyi/mill/issues/1901
class ZincIncrementalCompilationTests(fork: Boolean, clientServer: Boolean)
extends IntegrationTestSuite("zinc-incremental-compilation", fork, clientServer) {
val tests = Tests {
initWorkspace()
"incremental compilation only compiles changed files" - {
val successful = eval("app.compile")
assert(successful)

val appSrc = wd / "app" / "src" / "main" / "scala" / "App.scala"
val classes = wd / "out" / "app" / "compile.dest" / "classes"
val app = classes / "app" / "App.class"
val model = classes / "models" / "Foo.class"
assert(Seq(classes, app, model, appSrc).forall(os.exists))

val appSrcInfo1 = os.stat(appSrc)
val appInfo1 = os.stat(app)
val modelInfo1 = os.stat(model)

println("** second run **")
os.write.append(appSrc, "\n ")

val succ2nd = eval("app.compile")
assert(succ2nd)

val appSrcInfo2 = os.stat(appSrc)
val appInfo2 = os.stat(app)
val modelInfo2 = os.stat(model)

// we changed it
assert(appSrcInfo1.mtime != appSrcInfo2.mtime)
// expected to be re-compiled
assert(appInfo1.ctime != appInfo2.ctime)
// expected to be NOT re-compiled
assert(modelInfo1.ctime == modelInfo2.ctime)
}
}
}
11 changes: 6 additions & 5 deletions integration/local/src/local/local-tests.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package mill.integration
package local

object DocAnnotationsTests extends DocAnnotationsTests(fork = false, false)
object HygieneTests extends HygieneTests(fork = false, false)
object LargeProjectTests extends LargeProjectTests(fork = false, false)
object ScriptsInvalidationTests extends ScriptsInvalidationTests(fork = false, false)
object ScriptsInvalidationForeignTests extends ScriptsInvalidationForeignTests(fork = false, false)
object DocAnnotationsTests extends DocAnnotationsTests(fork = false, clientServer = false)
object HygieneTests extends HygieneTests(fork = false, clientServer = false)
object LargeProjectTests extends LargeProjectTests(fork = false, clientServer = false)
object ScriptsInvalidationTests extends ScriptsInvalidationTests(fork = false, clientServer = false)
object ScriptsInvalidationForeignTests extends ScriptsInvalidationForeignTests(fork = false, clientServer = false)
object ZincIncrementalCompilationTests extends ZincIncrementalCompilationTests(fork = false, clientServer = false)
1 change: 0 additions & 1 deletion integration/thirdparty/forked/src/Tests.scala
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ package forked

object AcyclicTests extends AcyclicTests(fork = true)
object AmmoniteTests extends AmmoniteTests(fork = true)
object BetterFilesTests extends BetterFilesTests(fork = true)
object JawnTests extends JawnTests(fork = true)
object UpickleTests extends UpickleTests(fork = true)
object CaffeineTests extends CaffeineTests(fork = true)
86 changes: 0 additions & 86 deletions integration/thirdparty/local/resources/better-files/build.sc

This file was deleted.

32 changes: 0 additions & 32 deletions integration/thirdparty/local/src/BetterFilesTests.scala

This file was deleted.

1 change: 0 additions & 1 deletion integration/thirdparty/local/src/local/Tests.scala
Original file line number Diff line number Diff line change
@@ -3,7 +3,6 @@ package local

object AcyclicTests extends AcyclicTests(fork = false)
object AmmoniteTests extends AmmoniteTests(fork = false)
object BetterFilesTests extends BetterFilesTests(fork = false)
object JawnTests extends JawnTests(fork = false)
object UpickleTests extends UpickleTests(fork = false)
object CaffeineTests extends CaffeineTests(fork = false)
19 changes: 16 additions & 3 deletions main/api/src/mill/api/PathRef.scala
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ package mill.api

import java.nio.{file => jnio}
import java.security.{DigestOutputStream, MessageDigest}
import scala.util.Using

import upickle.default.{ReadWriter => RW}

@@ -45,9 +46,21 @@ object PathRef {
val value = (attrs.mtime, attrs.size).hashCode()
updateWithInt(value)
} else if (jnio.Files.isReadable(path.toNIO)) {
val is = os.read.inputStream(path)
StreamSupport.stream(is, digestOut)
is.close()
val is =
try Some(os.read.inputStream(path))
catch {
case _: jnio.FileSystemException =>
// This is known to happen, when we try to digest a socket file.
// We ignore the content of this file for now, as we would do,
// when the file isn't readable.
// See https://github.com/com-lihaoyi/mill/issues/1875
None
}
is.foreach {
Using.resource(_) { is =>
StreamSupport.stream(is, digestOut)
}
}
}
}
}
2 changes: 1 addition & 1 deletion main/client/src/mill/main/client/MillClientMain.java
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ static void initServer(String lockBase, boolean setJnaNoSys) throws IOException,
}

public static void main(String[] args) throws Exception {
if (args.length > 1) {
if (args.length > 0) {
String firstArg = args[0];
if (Arrays.asList("-i", "--interactive", "--no-server", "--repl", "--bsp").contains(firstArg)) {
// start in no-server mode
7 changes: 3 additions & 4 deletions main/src/mill/MillConfig.scala
Original file line number Diff line number Diff line change
@@ -12,15 +12,14 @@ case class MillConfig(
home: os.Path = mill.api.Ctx.defaultHome,
@arg(
doc =
"""Run Mill in interactive mode and start a build REPL. In this mode, no
"""Run Mill in interactive mode and start a build REPL. This implies --no-server and no
mill server will be used. Must be the first argument."""
)
repl: Flag,
@arg(
name = "no-server",
doc =
"""Run Mill in interactive mode, suitable for opening REPLs and taking user
input. In this mode, no mill server will be used. Must be the first argument."""
"""Run Mill in single-process mode. In this mode, no mill server will be started or used. Must be the first argument."""
)
noServer: Flag,
@arg(
@@ -31,7 +30,7 @@ case class MillConfig(
short = 'i',
doc =
"""Run Mill in interactive mode, suitable for opening REPLs and taking user
input. In this mode, no mill server will be used. Must be the first argument."""
input. This implies --no-server and no mill server will be used. Must be the first argument."""
)
interactive: Flag,
@arg(name = "version", short = 'v', doc = "Show mill version and exit.")
8 changes: 8 additions & 0 deletions main/src/mill/main/MainModule.scala
Original file line number Diff line number Diff line change
@@ -389,6 +389,14 @@ trait MainModule extends mill.Module {
System.exit(0)
}

def init(evaluator: Evaluator, args: String*): Command[Unit] = T.command {
MainModule.evaluateTasks(
evaluator,
Seq("mill.scalalib.giter8.Giter8Module/init") ++ args,
selectMode = SelectMode.Single
)(identity).map(_.value)
}

private type VizWorker = (
LinkedBlockingQueue[(scala.Seq[_], scala.Seq[_], os.Path)],
LinkedBlockingQueue[Result[scala.Seq[PathRef]]]
6 changes: 0 additions & 6 deletions main/test/src/main/ClientServerTests.scala
Original file line number Diff line number Diff line change
@@ -42,12 +42,6 @@ class EchoServer extends MillServerMain[Int] {

object ClientServerTests extends TestSuite {

if (scala.util.Properties.isWin) {
// workaround for CI issue
// https://github.com/com-lihaoyi/mill/pull/1852#issuecomment-1114332274
System.setProperty("os.name", "Windows10")
}

val ENDL = System.lineSeparator()

def initStreams() = {
38 changes: 36 additions & 2 deletions readme.adoc
Original file line number Diff line number Diff line change
@@ -60,6 +60,10 @@ motivation:
* http://www.lihaoyi.com/post/BuildToolsasPureFunctionalPrograms.html[Build Tools as Pure Functional Programs]
* http://www.lihaoyi.com/post/MillBetterScalaBuilds.html[Mill: Better Scala Builds]

Mill is profiled using the
https://www.ej-technologies.com/products/jprofiler/overview.html[JProfiler Java Profiler],
by courtesy of EJ Technologies.

== How to build and test

Mill is built using Mill. To begin, first download & install Mill as described
@@ -228,12 +232,42 @@ corresponding version of Mill.

=== 'main' branch
:version: main
:prev-version: 0.10.5
:milestone: 64
:milestone-name: after 0.10.5

_Changes since {prev-version}:_

_For details refer to
{link-milestone}/{milestone}?closed=1[milestone {milestone-name}]
and the {link-compare}/{prev-version}\...{version}[list of commits]._




=== 0.10.5 - 2022-07-01
:version: 0.10.5
:prev-version: 0.10.4
:milestone: 63
:milestone-name: after 0.10.4
:milestone-name: 0.10.5

_Changes since {prev-version}:_

* New `init` command, to create new Mill projects from Gitter8 (g8) templates
* `PathRef` now gracefully ignores socket files. This also fixes an annoying issue when Mill was previously ran in a source directory.
* Fixed a bug with using `mill --repl` without any further arguments, which was introduced in Mill 0.10.2 and prevented proper no-server mode
* Fixed the `visualize` command which wasn't working on some newer JREs
* Improved Mill server support for Windows 11 and some Windows Server versions

* `ScalaModule` / `ZincWorkerModule`: Fixed incremental compilation issue with JRE 17 (and probably others)
* `TestModule` now better supports JUnit5 test suites
* `ScalaJsModule`: internal improvements to the stability of the Scala.js linker
* `ScalaNativeModule`: Added support for `nativeEmbedResources`
* `BSP`: improved handling of the `mill-build` module when the BSP client is IntelliJ IDEA

* Documentation updates and link fixes
* Various dependency updates

_For details refer to
{link-milestone}/{milestone}?closed=1[milestone {milestone-name}]
and the {link-compare}/{prev-version}\...{version}[list of commits]._
@@ -561,7 +595,7 @@ _Changes since {prev-version}:_
* `ScalaModule`: Support for Scala 3
* `CoursierModule`: Support customized dependency resolution (needed to work with ScalaFX)
* `TestModule`: Added new `testFramework` target and only support one test framework. Deprecated `testFrameworks` targets.
* `TestModule`: Added new convenience traits to configure popular test frameworks, e.g. `TestModule.Junit`, `TestModule.ScalaTest`, `TestModule.Utest`, and many more
* `TestModule`: Added new convenience traits to configure popular test frameworks, e.g. `TestModule.Junit4`, `TestModule.ScalaTest`, `TestModule.Utest`, and many more
* `Bloop`: Added support for foreign modules
* Better support for Windows environments
* Various internal improvements, cleanups, and deprecations
30 changes: 19 additions & 11 deletions scalajslib/src/mill/scalajslib/ScalaJSModule.scala
Original file line number Diff line number Diff line change
@@ -86,30 +86,31 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
def scalaJSToolsClasspath = T { scalaJSWorkerClasspath() ++ scalaJSLinkerClasspath() }

def fastLinkJS: Target[Report] = T.persistent {
linkTask(optimize = false, forceOutJs = false)()
linkTask(isFullLinkJS = false, forceOutJs = false)()
}

def fullLinkJS: Target[Report] = T.persistent {
linkTask(optimize = true, forceOutJs = false)()
linkTask(isFullLinkJS = true, forceOutJs = false)()
}

def fastOpt: Target[PathRef] = T {
getReportMainFilePathRef(linkTask(optimize = false, forceOutJs = true)())
getReportMainFilePathRef(linkTask(isFullLinkJS = false, forceOutJs = true)())
}

def fullOpt: Target[PathRef] = T {
getReportMainFilePathRef(linkTask(optimize = true, forceOutJs = true)())
getReportMainFilePathRef(linkTask(isFullLinkJS = true, forceOutJs = true)())
}

private def linkTask(optimize: Boolean, forceOutJs: Boolean): Task[Report] = T.task {
private def linkTask(isFullLinkJS: Boolean, forceOutJs: Boolean): Task[Report] = T.task {
linkJs(
worker = ScalaJSWorkerExternalModule.scalaJSWorker(),
toolsClasspath = scalaJSToolsClasspath(),
runClasspath = runClasspath(),
mainClass = finalMainClassOpt().toOption,
forceOutJs = forceOutJs,
testBridgeInit = false,
optimize = optimize,
isFullLinkJS = isFullLinkJS,
optimizer = scalaJSOptimizer(),
moduleKind = moduleKind(),
esFeatures = esFeatures(),
moduleSplitStyle = moduleSplitStyle()
@@ -157,7 +158,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
mainClass = mainClass,
forceOutJs = true,
testBridgeInit = testBridgeInit,
optimize = mode == FullOpt,
isFullLinkJS = mode == FullOpt,
optimizer = mode == FullOpt,
moduleKind = moduleKind,
esFeatures = esFeatures,
moduleSplitStyle = ModuleSplitStyle.FewestModules
@@ -170,7 +172,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
mainClass: Option[String],
forceOutJs: Boolean,
testBridgeInit: Boolean,
optimize: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: ModuleKind,
esFeatures: ESFeatures,
moduleSplitStyle: ModuleSplitStyle
@@ -193,7 +196,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>
mainClass,
forceOutJs,
testBridgeInit,
optimize,
isFullLinkJS,
optimizer,
moduleKind,
esFeatures,
moduleSplitStyle
@@ -254,6 +258,8 @@ trait ScalaJSModule extends scalalib.ScalaModule { outer =>

def moduleSplitStyle: Target[ModuleSplitStyle] = T { ModuleSplitStyle.FewestModules }

def scalaJSOptimizer: Target[Boolean] = T { true }

@internal
override def bspBuildTargetData: Task[Option[(String, AnyRef)]] = T.task {
Some((
@@ -293,7 +299,8 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule {
mainClass = None,
forceOutJs = true,
testBridgeInit = true,
optimize = false,
isFullLinkJS = false,
optimizer = scalaJSOptimizer(),
moduleKind = moduleKind(),
esFeatures = esFeatures(),
moduleSplitStyle = moduleSplitStyle()
@@ -308,7 +315,8 @@ trait TestScalaJSModule extends ScalaJSModule with TestModule {
mainClass = None,
forceOutJs = false,
testBridgeInit = true,
optimize = false,
isFullLinkJS = false,
optimizer = scalaJSOptimizer(),
moduleKind = moduleKind(),
esFeatures = esFeatures(),
moduleSplitStyle = moduleSplitStyle()
3 changes: 2 additions & 1 deletion scalajslib/src/mill/scalajslib/ScalaJSWorkerApi.scala
Original file line number Diff line number Diff line change
@@ -33,7 +33,8 @@ class ScalaJSWorker private (val bridgeWorker: worker.ScalaJSWorker, createdInte
main = main,
forceOutJs = true,
testBridgeInit = testBridgeInit,
fullOpt = fullOpt,
isFullLinkJS = fullOpt,
optimizer = fullOpt,
moduleKind = moduleKind,
esFeatures = esFeatures,
moduleSplitStyle = ModuleSplitStyle.FewestModules
6 changes: 4 additions & 2 deletions scalajslib/src/mill/scalajslib/worker/ScalaJSWorker.scala
Original file line number Diff line number Diff line change
@@ -130,7 +130,8 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable {
main: Option[String],
forceOutJs: Boolean,
testBridgeInit: Boolean,
fullOpt: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: api.ModuleKind,
esFeatures: api.ESFeatures,
moduleSplitStyle: api.ModuleSplitStyle
@@ -142,7 +143,8 @@ private[scalajslib] class ScalaJSWorker extends AutoCloseable {
main = main.orNull,
forceOutJs = forceOutJs,
testBridgeInit = testBridgeInit,
fullOpt = fullOpt,
isFullLinkJS = isFullLinkJS,
optimizer = optimizer,
moduleKind = toWorkerApi(moduleKind),
esFeatures = toWorkerApi(esFeatures),
moduleSplitStyle = toWorkerApi(moduleSplitStyle)
3 changes: 2 additions & 1 deletion scalajslib/worker-api/src/ScalaJSWorkerApi.scala
Original file line number Diff line number Diff line change
@@ -10,7 +10,8 @@ private[scalajslib] trait ScalaJSWorkerApi {
main: String,
forceOutJs: Boolean,
testBridgeInit: Boolean,
fullOpt: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: ModuleKind,
esFeatures: ESFeatures,
moduleSplitStyle: ModuleSplitStyle
29 changes: 19 additions & 10 deletions scalajslib/worker/0.6/src/ScalaJSWorkerImpl.scala
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ 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.{
ClearableLinker,
ESFeatures => ScalaJSESFeatures,
Linker,
ModuleInitializer,
@@ -25,21 +26,22 @@ import scala.ref.WeakReference

class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
private case class LinkerInput(
fullOpt: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: ModuleKind,
esFeatures: ESFeatures
)
private object ScalaJSLinker {
private val cache = mutable.Map.empty[LinkerInput, WeakReference[Linker]]
def reuseOrCreate(input: LinkerInput): Linker = cache.get(input) match {
private val cache = mutable.Map.empty[LinkerInput, WeakReference[ClearableLinker]]
def reuseOrCreate(input: LinkerInput): ClearableLinker = cache.get(input) match {
case Some(WeakReference(linker)) => linker
case _ =>
val newLinker = createLinker(input)
cache.update(input, WeakReference(newLinker))
newLinker
}
private def createLinker(input: LinkerInput): Linker = {
val semantics = input.fullOpt match {
private def createLinker(input: LinkerInput): ClearableLinker = {
val semantics = input.isFullLinkJS match {
case true => Semantics.Defaults.optimized
case false => Semantics.Defaults
}
@@ -57,14 +59,15 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
)
})

val useClosure = input.fullOpt && input.moduleKind != ModuleKind.ESModule
val useClosure = input.isFullLinkJS && input.moduleKind != ModuleKind.ESModule
val config = StandardLinker.Config()
.withOptimizer(input.fullOpt)
.withOptimizer(input.optimizer)
.withClosureCompilerIfAvailable(useClosure)
.withSemantics(semantics)
.withModuleKind(scalaJSModuleKind)
.withESFeatures(scalaJSESFeatures)
StandardLinker(config)

new ClearableLinker(() => StandardLinker(config), config.batchMode)
}
}

@@ -75,12 +78,18 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
main: String,
forceOutJs: Boolean, // ignored in 0.6
testBridgeInit: Boolean, // ignored in 0.6
fullOpt: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: ModuleKind,
esFeatures: ESFeatures,
moduleSplitStyle: ModuleSplitStyle // ignored in 0.6
): Either[String, Report] = {
val linker = ScalaJSLinker.reuseOrCreate(LinkerInput(fullOpt, moduleKind, esFeatures))
val linker = ScalaJSLinker.reuseOrCreate(LinkerInput(
isFullLinkJS = isFullLinkJS,
optimizer = optimizer,
moduleKind = moduleKind,
esFeatures = esFeatures
))
val sourceSJSIRs = sources.map(new FileVirtualScalaJSIRFile(_))
val jars =
libraries.map(jar => IRContainer.Jar(new FileVirtualBinaryFile(jar) with VirtualJarFile))
25 changes: 14 additions & 11 deletions scalajslib/worker/1/src/ScalaJSWorkerImpl.scala
Original file line number Diff line number Diff line change
@@ -31,7 +31,8 @@ import scala.ref.WeakReference

class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
private case class LinkerInput(
fullOpt: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: ModuleKind,
esFeatures: ESFeatures,
moduleSplitStyle: ModuleSplitStyle,
@@ -51,7 +52,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
newLinker
}
private def createLinker(input: LinkerInput): Linker = {
val semantics = input.fullOpt match {
val semantics = input.isFullLinkJS match {
case true => Semantics.Defaults.optimized
case false => Semantics.Defaults
}
@@ -95,9 +96,9 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
if (minorIsGreaterThanOrEqual(6)) withESVersion_1_6_plus(scalaJSESFeatures)
else withESVersion_1_5_minus(scalaJSESFeatures)

val useClosure = input.fullOpt && input.moduleKind != ModuleKind.ESModule
val useClosure = input.isFullLinkJS && input.moduleKind != ModuleKind.ESModule
val partialConfig = StandardConfig()
.withOptimizer(input.fullOpt)
.withOptimizer(input.optimizer)
.withClosureCompilerIfAvailable(useClosure)
.withSemantics(semantics)
.withModuleKind(scalaJSModuleKind)
@@ -148,7 +149,7 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
if (minorIsGreaterThanOrEqual(3)) withModuleSplitStyle_1_3_plus(partialConfig)
else withModuleSplitStyle_1_2_minus(partialConfig)

StandardImpl.linker(config)
StandardImpl.clearableLinker(config)
}
}
def link(
@@ -158,7 +159,8 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
main: String,
forceOutJs: Boolean,
testBridgeInit: Boolean,
fullOpt: Boolean,
isFullLinkJS: Boolean,
optimizer: Boolean,
moduleKind: ModuleKind,
esFeatures: ESFeatures,
moduleSplitStyle: ModuleSplitStyle
@@ -168,11 +170,12 @@ class ScalaJSWorkerImpl extends ScalaJSWorkerApi {
val useLegacy = forceOutJs || !minorIsGreaterThanOrEqual(3)
import scala.concurrent.ExecutionContext.Implicits.global
val linker = ScalaJSLinker.reuseOrCreate(LinkerInput(
fullOpt,
moduleKind,
esFeatures,
moduleSplitStyle,
dest
isFullLinkJS = isFullLinkJS,
optimizer = optimizer,
moduleKind = moduleKind,
esFeatures = esFeatures,
moduleSplitStyle = moduleSplitStyle,
dest = dest
))
val cache = StandardImpl.irFileCache().newCache
val sourceIRsFuture = Future.sequence(sources.toSeq.map(f => PathIRFile(f.toPath())))
11 changes: 11 additions & 0 deletions scalalib/src/TestModule.scala
Original file line number Diff line number Diff line change
@@ -214,6 +214,17 @@ object TestModule {
}
}

/**
* TestModule that uses JUnit 5 Framework to run tests.
* You may want to provide the junit dependency explicitly to use another version.
*/
trait Junit5 extends TestModule {
override def testFramework: T[String] = "net.aichler.jupiter.api.JupiterFramework"
override def ivyDeps: T[Agg[Dep]] = T {
super.ivyDeps() ++ Agg(ivy"net.aichler:jupiter-interface:0.9.0")
}
}

/**
* TestModule that uses ScalaTest Framework to run tests.
* You need to provide the scalatest dependencies yourself.
33 changes: 33 additions & 0 deletions scalalib/src/giter8/Giter8Module.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package mill.scalalib.giter8

import mill.T
import mill.define.{Command, Discover, ExternalModule}
import mill.modules.Jvm
import mill.scalalib.api.ZincWorkerUtil
import mill.scalalib._
import mill.BuildInfo
import mill.api.Loose

object Giter8Module extends ExternalModule with Giter8Module {
lazy val millDiscover = Discover[this.type]
}

trait Giter8Module extends CoursierModule {

def init(args: String*): Command[Unit] = T.command {
T.log.info("Creating a new project...")
val giter8Dependencies = resolveDeps(
T.task {
val scalaBinVersion = ZincWorkerUtil.scalaBinaryVersion(BuildInfo.scalaVersion)
Loose.Agg(ivy"org.foundweekends.giter8:giter8_${scalaBinVersion}:0.14.0")
}
)()

Jvm.runSubprocess(
"giter8.Giter8",
giter8Dependencies.map(_.path),
mainArgs = args,
workingDir = T.workspace
)
}
}
3 changes: 3 additions & 0 deletions scalalib/src/mill/scalalib/bsp/BspModule.scala
Original file line number Diff line number Diff line change
@@ -142,4 +142,7 @@ trait MillBuildTarget // (rootModule: BaseModule, ctx0: mill.define.Ctx)
os.makeDir(T.dest / "classes")
CompilationResult(T.dest / "dummy", PathRef(T.dest / "classes"))
}

/** Used in BSP IntelliJ, which can only work with directories */
def dummySources: Sources = T.sources(T.dest)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package example

object Hello extends App {
println("Hello world!")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package example

class MySuite extends munit.FunSuite {
test("hello") {
val obtained = 42
val expected = 43
assertEquals(obtained, expected)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

.bsp/
.metals/
.vscode/

out/
17 changes: 17 additions & 0 deletions scalalib/test/resources/giter8/hello.g8/src/main/g8/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

# $name;format="camel"$

This is a Scala hello world app, built with the Mill build tool.
You can refer to [Mill documentation](https://com-lihaoyi.github.io/mill/mill/Intro_to_Mill.html) on how to install it and much more!

Some basic commands:
```sh
# compile
mill $name;format="camel"$.compile

# run
mill $name;format="camel"$.run

# test
mill $name;format="camel"$.test
```
12 changes: 12 additions & 0 deletions scalalib/test/resources/giter8/hello.g8/src/main/g8/build.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import mill._, scalalib._

object $name;format="camel"$ extends ScalaModule {

def scalaVersion = "2.13.8"

object test extends Tests with TestModule.Munit {
def ivyDeps = Agg(
ivy"org.scalameta::munit::0.7.29"
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name=Scala Seed Project
description=A minimal Scala project.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$ClassName
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package hello;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class Junit5TestsA {

@Test
public void coreTest() {
assertEquals(Core.msg(), "Hello World");
}

@Test
@Disabled("for demonstration purposes")
public void skippedTest() {
// not executed
}

@ParameterizedTest
@ValueSource(strings = { "racecar", "radar" })
void palindromes(String candidate) {
assertTrue(isPalindrome(candidate));
}

static boolean isPalindrome(String str) {
String reversed = new StringBuilder(str).reverse().toString();
return str.equals(reversed);
}
}

class Junit5TestsB {

@Test
void packagePrivateTest() {
assertEquals(Core.msg(), "Hello World");
}
}
18 changes: 18 additions & 0 deletions scalalib/test/src/HelloJavaTests.scala
Original file line number Diff line number Diff line change
@@ -19,6 +19,11 @@ object HelloJavaTests extends TestSuite {
override def docJarUseArgsFile = true
override def moduleDeps = Seq(core)
object test extends Tests with TestModule.Junit4
object testJunit5 extends Tests with TestModule.Junit5 {
override def ivyDeps: T[Agg[Dep]] = T {
super.ivyDeps() ++ Agg(ivy"org.junit.jupiter:junit-jupiter-params:5.7.0")
}
}
}
}
val resourcePath = os.pwd / "scalalib" / "test" / "resources" / "hello-java"
@@ -81,6 +86,19 @@ object HelloJavaTests extends TestSuite {
v2._2(1).fullyQualifiedName == "hello.MyAppTests.coreTest",
v2._2(1).status == "Success"
)

val Right((v3, _)) = eval.apply(HelloJava.app.testJunit5.test())

val testResults = v3._2.map(t => (t.fullyQualifiedName, t.selector, t.status)).sorted
val expected = Seq(
("hello.Junit5TestsA", "coreTest()", "Success"),
("hello.Junit5TestsA", "palindromes(String):1", "Success"),
("hello.Junit5TestsA", "palindromes(String):2", "Success"),
("hello.Junit5TestsA", "skippedTest()", "Skipped"),
("hello.Junit5TestsB", "packagePrivateTest()", "Success")
)

assert(testResults == expected)
}
"failures" - {
val eval = init()
50 changes: 50 additions & 0 deletions scalalib/test/src/giter8/Giter8Tests.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package mill.scalalib.giter8

import mill.T
import mill.util.{TestEvaluator, TestUtil}
import utest._
import mill.api.Loose.Agg
import os.Path

object Giter8Tests extends TestSuite {

override def tests: Tests = Tests {
test("init") {
test("hello") {
val rootDir = os.temp.dir(prefix = "mill_giter8_test")
val template = getClass().getClassLoader().getResource("giter8/hello.g8").toExternalForm
val templateString =
if (template.startsWith("file:/") && template(6) != '/') {
template.replace("file:", "file://")
} else template

object g8Module extends TestUtil.BaseModule with Giter8Module {
override def millSourcePath: Path = rootDir
}

val evaluator = new TestEvaluator(g8Module)

val giter8Args = Seq(
templateString,
"--name=hello", // skip user interaction
"--description=hello_desc" // need to pass all args
)
val res = evaluator.evaluator.evaluate(Agg(g8Module.init(giter8Args: _*)))

val files = Seq(
os.sub / "build.sc",
os.sub / "README.md",
os.sub / "hello" / "src" / "Hello.scala",
os.sub / "hello" / "test" / "src" / "MyTest.scala"
)

assert(
res.failing.keyCount == 0,
res.values.size == 1,
files.forall(f => os.exists(rootDir / "hello" / f))
)
}
}
}

}
7 changes: 5 additions & 2 deletions scalalib/worker/src/mill/scalalib/worker/MockedLookup.scala
Original file line number Diff line number Diff line change
@@ -13,6 +13,9 @@ case class MockedLookup(am: VirtualFile => Optional[CompileAnalysis])
override def analysis(classpathEntry: VirtualFile): Optional[CompileAnalysis] =
am(classpathEntry)

override def definesClass(classpathEntry: VirtualFile): DefinesClass =
Locate.definesClass(classpathEntry)
override def definesClass(classpathEntry: VirtualFile): DefinesClass = {
if (classpathEntry.name.toString != "rt.jar")
Locate.definesClass(classpathEntry)
else (_: String) => false
}
}
Original file line number Diff line number Diff line change
@@ -474,7 +474,8 @@ class ZincWorkerImpl(

val store = FileAnalysisStore.binary(zincFile.toIO)

val converter = PlainVirtualFileConverter.converter
// Fix jdk classes marked as binary dependencies, see https://github.com/com-lihaoyi/mill/pull/1904
val converter = MappedFileConverter.empty
val classpath = (compileClasspath.iterator ++ Some(classesDir))
.map(path => converter.toVirtualFile(path.toNIO))
.toArray
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package mill.scalanativelib.api;

import sbt.testing.Framework;

public interface ScalaNativeWorkerApi {
@@ -20,6 +21,7 @@ NativeConfig config(String mainClass,
LTO nativeLTO,
ReleaseMode releaseMode,
boolean optimize,
boolean embedResources,
NativeLogLevel logLevel);

String defaultGarbageCollector();
11 changes: 10 additions & 1 deletion scalanativelib/src/ScalaNativeModule.scala
Original file line number Diff line number Diff line change
@@ -164,6 +164,14 @@ trait ScalaNativeModule extends ScalaModule { outer =>
// Whether to link `@stub` methods, or ignore them
def nativeLinkStubs = T { false }

/**
* Shall the resource files be embedded in the resulting binary file? Allows
* the use of getClass().getResourceAsStream() on the included files. Will
* not embed files with certain extensions, including ".c", ".h", ".scala"
* and ".class".
*/
def nativeEmbedResources = T { false }

// The LTO mode to use used during a release build
protected def nativeLTOInput: Target[Option[LTO]] = T.input {
readEnvVariable[LTO](T.env, "SCALANATIVE_LTO", LTO.values, _.value)
@@ -195,7 +203,8 @@ trait ScalaNativeModule extends ScalaModule { outer =>
nativeLTO(),
releaseMode(),
nativeOptimize(),
logLevel()
nativeEmbedResources(),
logLevel(),
)
}

48 changes: 29 additions & 19 deletions scalanativelib/worker/0.4/src/ScalaNativeWorkerImpl.scala
Original file line number Diff line number Diff line change
@@ -3,6 +3,8 @@ package mill.scalanativelib.worker
import java.io.File
import java.lang.System.{err, out}

import mill.scalanativelib.api.{GetFrameworkResult, LTO, NativeConfig, NativeLogLevel, ReleaseMode}
import sbt.testing.Framework
import scala.scalanative.util.Scope
import scala.scalanative.build.{
Build,
@@ -16,12 +18,19 @@ import scala.scalanative.build.{
NativeConfig => ScalaNativeNativeConfig
}
import scala.scalanative.nir.Versions
import mill.scalanativelib.api.{GetFrameworkResult, LTO, NativeConfig, NativeLogLevel, ReleaseMode}
import sbt.testing.Framework

import scala.scalanative.testinterface.adapter.TestAdapter

import scala.util.{Success, Try}

class ScalaNativeWorkerImpl extends mill.scalanativelib.api.ScalaNativeWorkerApi {
private def patchIsGreaterThanOrEqual(number: Int) = {
val patch = Versions.current.stripPrefix("0.4.")
Try(patch.toInt) match {
case Success(n) if n < number => false
case _ => true
}
}

def logger(level: NativeLogLevel) =
Logger(
traceFn = msg => if (level.value >= NativeLogLevel.Trace.value) err.println(s"[trace] $msg"),
@@ -51,30 +60,31 @@ class ScalaNativeWorkerImpl extends mill.scalanativelib.api.ScalaNativeWorkerApi
nativeLTO: LTO,
releaseMode: ReleaseMode,
nativeOptimize: Boolean,
nativeEmbedResources: Boolean,
logLevel: NativeLogLevel
): NativeConfig = {
val entry = Versions.current match {
case "0.4.0" | "0.4.1" | "0.4.2" => mainClass + "$"
case _ => mainClass
val entry = if (patchIsGreaterThanOrEqual(3)) mainClass else mainClass + "$"
var nativeConfig =
ScalaNativeNativeConfig.empty
.withClang(nativeClang.toPath)
.withClangPP(nativeClangPP.toPath)
.withTargetTriple(if (nativeTarget.isPresent) Some(nativeTarget.get) else None)
.withCompileOptions(nativeCompileOptions)
.withLinkingOptions(nativeLinkingOptions)
.withGC(GC(nativeGC))
.withLinkStubs(nativeLinkStubs)
.withMode(Mode(releaseMode.value))
.withOptimize(nativeOptimize)
.withLTO(ScalaNativeLTO(nativeLTO.value))
if (patchIsGreaterThanOrEqual(4)) {
nativeConfig = nativeConfig.withEmbedResources(nativeEmbedResources)
}
val config =
Config.empty
.withMainClass(entry)
.withClassPath(classpath.map(_.toPath))
.withWorkdir(nativeWorkdir.toPath)
.withCompilerConfig(
ScalaNativeNativeConfig.empty
.withClang(nativeClang.toPath)
.withClangPP(nativeClangPP.toPath)
.withTargetTriple(if (nativeTarget.isPresent) Some(nativeTarget.get) else None)
.withCompileOptions(nativeCompileOptions)
.withLinkingOptions(nativeLinkingOptions)
.withGC(GC(nativeGC))
.withLinkStubs(nativeLinkStubs)
.withMode(Mode(releaseMode.value))
.withOptimize(nativeOptimize)
.withLTO(ScalaNativeLTO(nativeLTO.value))
)
.withCompilerConfig(nativeConfig)
.withLogger(logger(logLevel))
new NativeConfig(config)
}
17 changes: 10 additions & 7 deletions testrunner/src/TestRunner.scala
Original file line number Diff line number Diff line change
@@ -61,7 +61,10 @@ object TestRunner {
val publicConstructorCount =
cls.getConstructors.count(c => Modifier.isPublic(c.getModifiers))

if (
if (framework.name() == "Jupiter") {
// sbt-jupiter-interface ignores fingerprinting since JUnit5 has its own resolving mechanism
Some((cls, fingerprints.head))
} else if (
Modifier.isAbstract(cls.getModifiers) || cls.isInterface || publicConstructorCount > 1
) {
None
@@ -204,16 +207,16 @@ object TestRunner {

TestArgs(
frameworks,
classpath,
arguments,
classpath.toIndexedSeq,
arguments.toIndexedSeq,
sysProps.grouped(2).foldLeft(Map[String, String]()) { (map, prop) =>
map.updated(prop(0), prop(1))
},
outputPath,
colored = Seq("true", "1", "on", "yes").contains(colored),
testCp = testCp,
homeStr = homeStr,
globFilters
globFilters.toIndexedSeq
)
}
}
@@ -328,7 +331,7 @@ object TestRunner {
val testClasses = discoverTests(cl, framework, testClassfilePath)

val tasks = runner.tasks(
for ((cls, fingerprint) <- testClasses.toArray if classFilter(cls))
for ((cls, fingerprint) <- testClasses.iterator.toArray if classFilter(cls))
yield new TaskDef(
cls.getName.stripSuffix("$"),
fingerprint,
@@ -385,7 +388,7 @@ object TestRunner {
e.status().toString,
ex.map(_.getClass.getName),
ex.map(_.getMessage),
ex.map(_.getStackTrace)
ex.map(_.getStackTrace.toIndexedSeq)
)
}

@@ -405,7 +408,7 @@ object TestRunner {
cl: ClassLoader
): sbt.testing.Framework = {
cl.loadClass(frameworkName)
.newInstance()
.getDeclaredConstructor().newInstance()
.asInstanceOf[sbt.testing.Framework]
}