A detailed explanation of the dependencies between SBT tasks in Linux

Source: Internet
Author: User
Tags sleep


In the BUILD.SBT in the project, there are task2 <<= Task1 map {...} when the task is defined, this <<= method is a little obscure, and after reading the SBT in action it is SBT 0 .12 or previous practice, SBT 0.13 is not so used, direct access to the next task1.value on line, so the front can be rewritten as task2: = {task1.value; ...}, which also makes defining task dependencies consistent with common tasks. The new notation benefits from the macro features of Scala 2.10, which is also mentioned later.

For situations that depend on multiple tasks, this is the case in front of SBT 0.13, assuming that there are three tasks (Task1, Task2, and TASK3)

Val Task1 = Taskkey[int] ("Task 1")
Val task2 = Taskkey[int] ("Task 2")
Val task3 = Taskkey[int] ("Task 3")

If TASK3 relies on Task1 and task 2

SBT 0.13 before and after the version of the wording is

SBT 0.12 and earlier, of course, SBT 0.13 can also write
Http://www.scala-sbt.org/0.12.2/docs/Detailed-Topics/Tasks.html#dependencies
Task3 <<= (Task1, Task2). Map (t1, t2) => t1 + T2)//task1, task2 concurrent execution

After SBT 0.13, recommend this new style
TASK3: = Task1.value + task2.value//task1, task2 concurrent execution
Like a task. The Value property is actually a macro definition, the source code


@compileTimeOnly ("' value ' can be used within a task or setting macro, such as: =, + =, ++=, Def.task, or def.setting." )
def VALUE:T = Macro Inputwrapper.valuemacroimpl[t]

The so-called Scala macros are very similar to the macro effect of C + +, just imagine that SBT will have a macro substitution operation before executing TASK3, Task1 and Task2 tasks are performed at Task1.value, Task2.value, and the results are put here, and then Add the two results together. SBT only macros for Task.value in a task or setting definition, and if you call Task.value in a custom method you will receive the same compilation error as the one on the macro definition.

To demonstrate that the macro is performed before its own task, you can look at one of the following examples:

Task1: = {
println ("Task1"); 1
}

Task2: = {
println ("Task2"); 2
}

Task3: = {
if (false) {
println ("TASK3")//Because if condition is false, it will not print TASK3
Task1.value//This macro is processed, so it is not controlled by the previous if condition
} else {
Task2.value
}
}
That's what happens when you do it.

➜test SBT
[INFO] Set current project to test (in build file:/users/uqiu/test/)
> Show Task3
Task1
Task2
[INFO] 2
[Success] Total time:0 S, completed APR, 2016 10:54:20 PM
> Inspect Tree task3
[INFO] *:task3 = task[int]
[INFO] +-*:task1 = task[int]
[INFO] +-*:task2 = task[int]

Visible from the top, although Task1.value is written in the if (false) condition, but it is still executed, which is the credit of the macro processing, where the ' println (' Task3 ') is controlled by the false condition.

The tasks that are relied on in SBT are executed concurrently, so it is not because of who writes in front of who executes first, see an example

Task1: = {
Thread.Sleep (500)//pause for half a second
println ("Task1"); 1
}

Task2: = {
println ("Task2"); 2
}

TASK3: = Task1.value + task2.value//Although Task1 is written before Task2, the results of the Task2 are printed first, and they are executed concurrently.
Execute TASK3

> Task3
Task2
Task1

Visible Task1 and Task2 are executed concurrently, task2 do not need to wait for Task1

So how do you make task dependencies sequential? You can use the DependsOn () method, and also for <<= and: = can be written in two ways

Task3 <<= Task2.dependson (TASK1)

TASK3: = Task2.dependson (TASK1). Value//recommend this new wording
So Task2 is executed after Task1, DependsOn () can be threaded, and its prototype is DependsOn (tasks:anyinittask*), so it can accept multiple arguments at the same time (they are executed concurrently)

How do I do something before I have a built-in task? Call the original task to its reliance on other tasks, such as performing a task before run, and also listing both new and old ways of writing

Run <<= (run in Runtime). DependsOn Task2

Run: = (run in Runtime). DependsOn (TASK2). evaluated//recommend this new wording
SBT Official document: Modifying an Existing Task.

How do I make dependencies dependent on each other? Like dynamic dependencies, or the example above, to execute run in Runtime when the task execution result is 100, imagine the following code:

Run: = {
if (Task1.value = = 100) {
(Run in Runtime). Evaluated
}
}
Here are two questions: 1 Task1 and (run in Runtime) are executed concurrently, 2) (run in Runtime) the macro processing phase before the condition is judged is done first. So (run in Runtime) executes anyway, regardless of the if condition.

For this, we have a less perfect solution, or with the DependsOn () method, Task1 in some cases invoke Sys.error ("error occurs"), then all the tasks behind it will no longer execute, back to the SBT control. The fragment code is as follows:


Task1: = {
Thread.Sleep (500)
println (12); 1
}

Task1: = {
if (Parallelexecution.value)
Sys.error ("Can ' t run in parallel mode")
Else 2
}
There is a Scala file in the project


Object Main extends App {
println ("Hello World.")
}

So if run is performing normally, you can output Hello world. Now look at the condition control execute run

Sbt-sys.error

Parallelexecution defaults to True, so the first time you perform TASK3 run is not executed directly to the SBT console, and then the parallelexecution is set to False, TASK3 can perform the run task.

See SBT Official documentation: Handling failure

SBT 0.13 seems to have a more precise control of the conditions for performing tasks: Dynamic computations with Def.taskdyn, it is OK to try it:


Val stringtask = taskkey[string] ("String task")
Val inttask = Taskkey[int] ("Int task")
Val mytask = Taskkey[unit] ("My Task")

Stringtask: = "Dev"

Inttask: = {
println ("Inttask"); 5
}

Val Dynamic = Def.taskdyn {
Decide what to evaluate based on the value of ' Stringtask '
if (Stringtask.value = = "Dev")
Def.task {
3
}
Else
Create the production task:only evaluated if the value
Of the stringtask is not "dev"
Def.task {
Inttask.value + 5
}
}

MyTask: = {
Val num = Dynamic.value
println (S "Number selected was $num")
}

Execution effect:

Sbt-taskdyn

The direction is right, just for Inputtask run in Runtime, there is nowhere in Def.task, written


Def.task {
(Run in Runtime). Value
}
This does not perform the built-in run task, and is not allowed to be written in the Def.task (run in Runtime). evaluated. It is not yet clear how to apply dynamic tasks to modifying the built-in run tasks.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.