Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
11 changes: 11 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,17 @@ 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, since mill wouldn't be able to build
// the dependency tree. 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.
// Common strategies around this are:
// 1. Define the values outside of a task, so Mill knows how to create the anonymous
// tasks before evaluation starts.
// 2. Put the value itself into a task, so it can be properly ordered to be evaluated
// before it's dependencies.
// 3. 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