-
-
Notifications
You must be signed in to change notification settings - Fork 347
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove Ammonite as a dependency, handle script running and bootstrapping ourselves #2377
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…local.DocAnnotationsTests.test
…nc happy, fixes mill.integration.forked.DocAnnotationsTests.test
…f the other tests in that suite now pass
This was referenced Apr 23, 2023
lihaoyi
added a commit
that referenced
this pull request
Apr 29, 2023
…h management to allow testing (#2476) Fixes #2474 These were overlooked in #2377 and deleted, and were not covered by any tests. But it's straightforward to put them back. # Major Changes 1. Put back `MillIvy.scala` and call it in `MillBuildRootModule.scala` # Testing 1. I added an example test `example/misc/6-contrib-import` to both exercise the code as well as serve as an example we can include in our docs 2. In order to allow usage of contrib module in `.local` integration and example tests, I moved the handling of Mill test classpath overrides from `Util.millProjectModule` to `CoursierSupport#resolveDependencies`. This lets us be more override contrib modules dependency resolution, even though they don't have a neat single location for us to call our `millProjectModule` helper. 3. I refactored `millProjectModule` to not need a `key`, so we just compute the key based on the dependency name, keeping them consistent and removing an unnecessary degree of freedom 4. The local-testing-classpath-overrides were moved from using JVM system properties to instead use classpath resources: we look for overrides in `mill/local-test-overrides/*`. This should remove any security worries: 1. Before you only needed to modify the JVM props or `JAVA_OPTS` environment variable, and could replace the code of a Mill module to any local filesystem path 2. Now, you need access to modify the Mill classpath to trigger the test overrides, and at that point you already have access to modifying the Mill classfiles being executed anyway While it probably was not strictly necessary to clean up the test classpath overrides logic as part of this PR, the status quo in master was a pile of hacks, and I didn't feel like adding another hack to get `.local` testability of contrib libraries working. With these changes, contrib libraries work the same as the existing Mill test classpath overrides, and things are cleaned up so much that the net lines of code for this PR is negative There's still more cleanup to do in `build.sc`, but those can come in follow up PRs
This was referenced May 2, 2023
lihaoyi
added a commit
that referenced
this pull request
May 5, 2023
Fixes #2485 We take the `config.imports` field and pass it to `MillIvy.processMillIvyDepSignature` inside `ivyDeps`. This was overlooked in #2377, but seems easy enough to put back Honestly not super sure how to test this. But when I run ``` ./mill -i dev.run example/tasks/3-anonymous-tasks -i --import ivy:com.lihaoyi::mill-contrib-bloop:0.11.0-M8 mill.contrib.bloop.Bloop/install ``` On main branch, I get ``` Cannot resolve external module mill.contrib.bloop.Bloop ``` On this PR I get ``` java.lang.NoSuchMethodError: 'java.lang.ThreadLocal mill.eval.Evaluator$.currentEvaluator()' mill.contrib.bloop.Bloop$$anonfun$$lessinit$greater$1.apply(Bloop.scala:8) mill.contrib.bloop.Bloop$$anonfun$$lessinit$greater$1.apply(Bloop.scala:8) ``` Seems like there's a binary incompatibility, but at least the `--import` flag took effect?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
The basic idea is that instead of relying on Ammonite to evaluate the
build.sc
and return us amill.define.BaseModule
value, we insteadFirst instantiate an in-memory
MillBuildRootModule
, which is a specialScalaModule
configured to readbuild.sc
and transform it intoBuild.scala
before compiling it with the necessary classpathUse a
mill.eval.Evaluator
to callrunClasspath
on theMillBootstrapModule
, which gives us a list of files and folders that are necessary to use itPut the files and folders into a
java.net.URLClassloader
to load it into the JVM, and use java reflection to fish out the finalmill.define.BaseModule
runtime valueThese are all largely things that were already happening before, just inside the guts of the Ammonite script runner, and mixed in with a bunch of other Ammonite REPL stuff we don't want, and via parallel code paths (e.g.
ammonite.compiler.Compiler
vsmill.scalalib.worker.ZincWorker
). By pulling them out, we can re-use the bulk ofScalaModule
logic we already have, and just need to do the minimal amount of classloader plumbing to get us what we wantMajor Code Changes
In order to let us depend on
ScalaModule
withinMillMain
, we need to split outMillMain
from the rest ofmain/
to avoid a circular dependency withscalalib/
. For now I dumped them in arunner/
module that depends on bothmain/
andscalalib/
, along with similar classes likeBspContext.scala
,GraphUtils.scala
, etc.Vendored/adapted a bunch of Ammonite code:
Parsers.scala
,Classpath.scala
,Colors.scala
,class AnsiNav
,Watchable.scala
,LineNumberPlugin.scala
,Util.scala
The old
MillMain
/MainRunner
/RunScript
logic has been reorganized intoMillMain
/MillBuildBootstrap
/MillBuildModule
:a.
MillBuildModule
is a hard-codedbuild.sc
file. This module knows how to parse thebuild.sc
, walk its import$file
/$ivy
, and generate the relevantgeneratedSources
/ivyDeps
for it to be compiled as a normalScalaModule
with the appropriate compiler-plugins/scala-version/etc.b.
MillBuildBootstrap
performs the main bootstrapping logic: creating aMillBootModule
, evaluating itsrunClasspath
, loading the classfiles into a classloader, grabbing the resultantBaseModule
from that classloader and then evaluating the targets that the user asked forc.
MillMain
is just the program entrypoint, mostly unchanged except we replace using ofMainRunner
withMillBootstrap
Removed the
mill -i
build REPL. We can consider adding it back in future if necessary, but for now the last poll basically indicated it is not used and it's not really well maintained.Removed all Ammonite dependencies from Mill's own
build.sc
EvaluatorState
is renamed toRunnerState
, and now contains a list ofFrame
s each one representing the output of one level of the meta-buildTop-level modules are now supported: simply define a module at the top level of your
build.sc
withextends mill.runner.BaseModule
, and it will be treated as the top-level module for resolving tasks and submodules. We make use of this for supporting meta-builds e.g.mill-build/build.sc
Smaller Code Changes
Made
PathRef#toString
use the same string asupickle.default.write(pathRef)
Consolidated all the
stdin
/stdout
/stderr
triples into oneSystemStreams
class to make them easier to pass aroundAdded a bunch more explicit dependencies that Mill was previously inheriting from Ammonite:
coursier
,requests
,scalaparse
etc.Consolidated a bunch of custom
implicit def
s withimport mill.main.TokenReaders._
Added an
--enable-ticker <bool>
flag, which unlike--disable-ticker
can be passedtrue
orfalse
. We now automatically enable or disable the ticker based onmainInteractive
, which is probably what most people want, and you can use--enable-ticker <bool>
to override it either waySimplified the computation of script dependency-based invalidation, now just using file-paths rather than class names and avoiding the confusing conversions back and forth
We dump the
RunnerState.Frame
to disk after everyMillBuildBootstrap.evaluate
call, to support both automated testing as well as manual debugging when things go wrong.Testing
All existing tests in the test suite pass
I moved all
ScriptTestSuite
s that rely onMillMain
into theintegration/
test folder, since now they rely not just on the stuff inmain/
but also the stuff inrunner/
Made the
bspWorkerLibs
task use our standard way of choosing between local classpath and ivy deps, to allow it to be tested locally without needing to publishLocalI added a few new tests:
a.
MultiLevelBuildTests
, which takes a 3-level build (build.sc
,mill-build/build.sc
,mill-build/mill-build/build.sc
) and walks through making changes (valid, parse error, compile error, runtime error) to various levels of the project and ensuring that the output/error, watched files, classloader invalidation, etc. all works as expectedb.
ParseErrorTests
andCompileErrorTests
, to make sure the messages are shown properly with proper line/col numbersc.
TopLevelModuleTests
, to exercise the new top-leval module functionalityI modified the
integration.local
tests to persist theRunnerState
between command invocations, so now it behaves more likeintegration.server
thanintegration.forked
Made
contrib/scoverage/test/src/mill/contrib/scoverage/HelloWorldTests.scala
tests pass on repos not namedmill
(so it can pass when run ongithub.com/lihaoyi/mill-1
Consolidated
ScriptTestSuite
intoIntegrationTestSuite
and standardized all test suites on using that traitTODO
Some story around how the
MillBuildModule
can share things with the normalbuild.sc
modules. Do they getclean
ed together? CanMillBuildModule
be inspected from the CLI? Can they share theirZincWorker
?Can we unify the
mill.runner.MillBuildModule
withmill.scalalib.bsp.MillBuildModule
?