-
-
Notifications
You must be signed in to change notification settings - Fork 415
Simple YAML-backed modules and single-file script modules #5836
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
base: main
Are you sure you want to change the base?
Conversation
…ll (com-lihaoyi#5820)"" This reverts commit 72db1f3.
ecae588
to
32888ba
Compare
7e884cf
to
7bf6fae
Compare
7bf6fae
to
b3ab4f0
Compare
f7cf97c
to
fb36045
Compare
Very cool feature! It's great not having to wait on the Scala compiler to compile the build.
|
If we somehow could avoid the need to have a concrete class, that would be cool. Instead of reflectively instantiating a class (which needs to be prepared for just this special use case), we want to use arbitrary existing Mill modules which are |
Code-generating backing Scala files for It does mean we would not be able to avoid using the Scala compiler to compile things. On the other hand, it would mean that we'd get the ability to refer to the But any error messages in the codegen would point at the generated code, which is less nice Not obvious which way is better, but it's something we can consider |
912d4d5
to
167d73c
Compare
I think the generated code should only use well tested code blocks, so the chance of a compile error is rather low, since if we managed to fully generate the code, we already know how to map each found YAML section to such a tested code block. Recompilation is probably only needed, if the (We might even have pre-compiled backing impls for most polular traits like |
We should move the discussion of the topic into a dedicated issue. |
CC @alexarchambault @arturaz if you have a moment to review this PR and feature proposal it would be great to get your thoughts as well |
Due to time constraints, I couldn't make a thorough review. OTOH, I fear an accidental/premature merge of this feature before we had a proper discussion, which I think is necessary. I want to remind us that once, we merge, we need to stick to that feature, since it is rather tightly coupled (located inside the existing modules, special CLI handling, ...). In addition to my previous comments and ideas, which are not directly related to this PR but to the general concept, here are some quick notes regarding this PR. File namesThe
Should we use Option handlingAlso, I think we should not skip the need to pass a Specifying an alternative build file with Simple modulesWe should not make the simple modules like To establish some naming pattern, we could place all the simple support files/classes in a |
This PR implements a way to define "Simple Modules" based on
mill.yaml
files or single.java
/.scala
/.kt
files with//|
build headers. This should make Mill more appealing for small projects, where the use of abuild.mill
file adds significant boilerplate and complexity. Most small projects need minimal customization of the build, and so the full Scala.mill
syntax provides no value over a more lightweight config-only approach. This PR also allows interop between simple YAML modules and custom module classes written inmill-build/src/
, to allow a gradual transition to the more flexible programmatic configurationSimple Module with
mill.yaml
mill.yaml
test/mill.yaml
Single-File Module with
.java
,.scala
, or.kt
Foo.scala
Implementation
Each
mill.yaml
simple module or*.{java,scala,kt}
script file on disk is instantiated into anExternalModule
in Mill, and can be configured via YAML data and depend on each other and on traditional "Programmatic Modules" (and vice versa). Each one instantiates amill.simple.SimpleModule
specified viaextends:
, and users can define their own concrete subclass ofSimpleModule
to use in their simple modules if the defaults do not do everything they want.mill.Module
s, you can run multiple simple modules or script files together with+
, or run them together with programmatic modules, or use them withshow
orinspect
. They also can depend on each other arbitrarily, since in the end they are allmill.Module
s in the Mill daemon classloaderParsing the query selectors is done by first attempting a parse-and-resolution for normal programmatic modules and tasks, and only if that fails do we attempt a parse-and-resolution for simple yaml-backed modules. This preserves backwards compatibility by ensuring queries that resolved to programmatic modules in the past continue to do so unchanged, while allowing a concise syntax for referencing simple yaml-backed modules
We re-use most of the infrastructure from Mill's existing YAML build headers, though refactored so the YAML metadata can apply to arbitrary modules rather than only the root meta-build module.
As we need to instantiate these modules reflectively, we cannot use
trait
s orabstract class
es, and so the modules thatmill.yaml
files or single-file scripts use inextends
need to be concrete classes. These are configured to take aSimpleModule.Config
case class
injected by Mill containing non-task metadata like the script file path andmoduleDeps
, though we can extend it to contain additional fields in future if necessaryclass
modules need to be stubbed out with= Task { ??? }
TODO
MavenModule
/MavenKotlinModule
/SbtModule
mill.yaml
files and build headersSupersedes #5826