Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions example/fundamentals/tasks/3-anonymous-tasks/build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ def printFileData(fileName: String) = Task.Command {
// anywhere and passed around any way you want, until you finally make use of them
// within a downstream task or command.
//
// Anonymous tasks work well when parameters are known at task definition time. Dynamically
// generated inputs can not be used with Anonymous Tasks, as this would break caching.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"as this would break caching." is wrong. It's not about caching, but definition/dependency order.

Since we need to know the parameters before creating the task, but the tasks need to be created before we can start evaluation, we have a classic hen-or-egg problem.

Copy link
Member

@lefou lefou Sep 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are three strategies to resolve this:

  • define the values outside of a task, so Mill knows how to create the anonymous tasks before evaluation starts
  • put the value itself into a task, so it can be properly ordered to be evaluated before it's dependencies
  • Make it not a task but a normal def

//
// While an anonymous task ``foo``'s own output is not cached, if it is used in a
// downstream task `baz` and the upstream task `bar` hasn't changed,
// ``baz``'s cached output will be used and ``foo``'s evaluation will be skipped
Expand Down
62 changes: 62 additions & 0 deletions example/fundamentals/tasks/8-inheritance-and-chaining/build.mill
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package build
import mill.*
import mill.api.TaskCtx

trait BaseModule extends Module {
def generate = Task {
val output = Task.dest / "generated.txt"
os.write(output, "hello")
PathRef(output)
}
}

// This module uses the base implementation unchanged
// Calling generate here will create:
// out/moduleA/generate.dest/generated.txt
object moduleA extends BaseModule

// When overriding tasks, never modify the parent task's output.
// Instead, create new output in your own task's destination folder
// Here we will generate two files in the output:
// out/moduleB/generate.super/BaseModule.dest/generated.txt (parent output)
// out/moduleB/generate.dest/processed.txt (this module's output)
// Note: We can not over write the original contents of
// generated.txt, because it is in a different output destination
object moduleB extends BaseModule {
override def generate = Task {
val parentResult = super.generate()
val parentContent = os.read(parentResult.path)
val processed = parentContent
.replaceAll("hello", "world")
.trim

writeData(processed, "processed.txt")
}

// Helper function for writing data within a task context
// Note: This is a regular function, not a Task, so it can accept
// runtime parameters. It uses implicit TaskCtx to access Task.dest
private def writeData(data: String, name: String)(implicit ctx: TaskCtx): PathRef = {
val outputPath = ctx.dest / name
os.write(outputPath, data)
PathRef(outputPath)
}
}

// We can also acheive similar results by chaining tasks together.
object moduleC extends BaseModule {
override def generate = Task {
processGenerated()
}

def processGenerated = Task {
val parentResult = super.generate()
val parentContent = os.read(parentResult.path)
val processed = parentContent
.replaceAll("hello", "world")
.trim
val outputPath = Task.dest / "processed.txt"
os.write(outputPath, processed)
PathRef(outputPath)
}
}
4 changes: 4 additions & 0 deletions website/docs/modules/ROOT/pages/fundamentals/tasks.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,7 @@ include::partial$example/fundamentals/tasks/6-workers.adoc[]

include::partial$example/fundamentals/tasks/3-anonymous-tasks.adoc[]

=== Inheritance and Chaining of Tasks

include::partial$example/fundamentals/tasks/8-inheritance-and-chaining.adoc[]

Loading