mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
180 lines
4 KiB
V
180 lines
4 KiB
V
module build
|
|
|
|
import os
|
|
|
|
@[heap; noinit]
|
|
pub struct BuildContext {
|
|
mut:
|
|
// should_run caches the result of should_run from tasks.
|
|
should_run map[string]bool
|
|
tasks []Task
|
|
pub mut:
|
|
// default is the default task to run when no others are provided.
|
|
default ?string
|
|
}
|
|
|
|
@[heap; noinit]
|
|
pub struct Task {
|
|
run fn (Task) ! @[required]
|
|
should_run fn (Task) !bool @[required]
|
|
// repeatable controls whether or not this task can run multiple times per build cycle
|
|
repeatable bool
|
|
pub:
|
|
name string
|
|
help string
|
|
depends []string
|
|
mut:
|
|
did_run bool
|
|
}
|
|
|
|
@[params]
|
|
pub struct BuildContextParams {
|
|
pub:
|
|
default ?string
|
|
}
|
|
|
|
@[params]
|
|
pub struct TaskParams {
|
|
pub:
|
|
name string @[required]
|
|
help string
|
|
depends []string
|
|
should_run fn (Task) !bool = |self| true
|
|
run fn (Task) ! @[required]
|
|
// repeatable controls whether or not this task can run multiple times per build cycle
|
|
repeatable bool
|
|
}
|
|
|
|
@[params]
|
|
pub struct ArtifactParams {
|
|
pub:
|
|
name string @[required]
|
|
help string
|
|
depends []string
|
|
should_run fn (Task) !bool = |self| !os.exists(self.name)
|
|
run fn (Task) ! @[required]
|
|
// repeatable controls whether or not this task can run multiple times per build cycle
|
|
repeatable bool
|
|
}
|
|
|
|
// context creates an empty BuildContext.
|
|
pub fn context(params BuildContextParams) BuildContext {
|
|
return BuildContext{
|
|
default: params.default
|
|
}
|
|
}
|
|
|
|
// task creates a task for the given context.
|
|
pub fn (mut context BuildContext) task(config TaskParams) {
|
|
if context.get_task(config.name) != none {
|
|
eprintln('error: task already exists with name `${config.name}`')
|
|
exit(1)
|
|
}
|
|
context.tasks << Task{
|
|
should_run: config.should_run
|
|
run: config.run
|
|
name: config.name
|
|
help: config.help
|
|
depends: config.depends
|
|
}
|
|
}
|
|
|
|
// artifact creates an artifact task for the given context.
|
|
pub fn (mut context BuildContext) artifact(config ArtifactParams) {
|
|
if context.get_task(config.name) != none {
|
|
eprintln('error: task already exists with name `${config.name}`')
|
|
exit(1)
|
|
}
|
|
context.tasks << Task{
|
|
should_run: config.should_run
|
|
run: config.run
|
|
name: config.name
|
|
help: config.help
|
|
depends: config.depends
|
|
repeatable: config.repeatable
|
|
}
|
|
}
|
|
|
|
// get_task gets the task with the given name.
|
|
pub fn (mut context BuildContext) get_task(name string) ?&Task {
|
|
for mut task in context.tasks {
|
|
if task.name == name {
|
|
return mut task
|
|
}
|
|
}
|
|
return none
|
|
}
|
|
|
|
// exec executes the task with the given name in the context.
|
|
pub fn (mut context BuildContext) exec(name string) {
|
|
if mut task := context.get_task(name) {
|
|
task.exec(mut context)
|
|
} else {
|
|
eprintln('error: no such task: ${name}')
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
// exec runs the given task and its dependencies.
|
|
pub fn (mut task Task) exec(mut context BuildContext) {
|
|
if task.did_run && !task.repeatable {
|
|
println(': ${task.name} (skipped)')
|
|
return
|
|
}
|
|
|
|
if task.name !in context.should_run {
|
|
context.should_run[task.name] = task.should_run(task) or {
|
|
eprintln('error: failed to call should_run for task `${task.name}`: ${err}')
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
if !context.should_run[task.name] {
|
|
println(': ${task.name} (skipped)')
|
|
return
|
|
}
|
|
|
|
for dep in task.depends {
|
|
if dep == task.name {
|
|
eprintln('error: cyclic task dependency detected, `${task.name}` depends on itself')
|
|
exit(1)
|
|
}
|
|
|
|
context.exec(dep)
|
|
}
|
|
println(': ${task.name}')
|
|
task.did_run = true
|
|
task.run(task) or {
|
|
eprintln('error: failed to run task `${task.name}`: ${err}')
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
// run executes all tasks provided through os.args.
|
|
pub fn (mut context BuildContext) run() {
|
|
// filter out options
|
|
mut tasks := os.args[1..].filter(|it| !it.starts_with('-'))
|
|
|
|
// check options
|
|
if '--tasks' in os.args || '-tasks' in os.args {
|
|
println('Tasks:')
|
|
for _, task in context.tasks {
|
|
println('- ${task.name}: ${task.help}')
|
|
}
|
|
return
|
|
}
|
|
|
|
if tasks.len == 0 {
|
|
if context.default != none {
|
|
tasks << context.default
|
|
} else {
|
|
eprintln('error: no task provided, run with `--tasks` for a list')
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
// execute tasks
|
|
for arg in tasks {
|
|
context.exec(arg)
|
|
}
|
|
}
|