/
TaskInputs.html
230 lines (216 loc) · 14.6 KB
/
TaskInputs.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Task Inputs/Dependencies — sbt Documentation</title>
<link rel="stylesheet" href="../_static/style.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/issuetracker.css" type="text/css" />
<link rel="stylesheet" href="../_static/base.css" type="text/css" />
<link rel="stylesheet" href="../_static/docs.css" type="text/css" />
<link rel="stylesheet" href="../_static/syntax.css" type="text/css" />
<link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Exo:300,400,600,700" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '0.12.1',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="../_static/jquery.js"></script>
<script type="text/javascript" src="../_static/underscore.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<script type="text/javascript" src="../../../versions.js"></script>
<script type="text/javascript" src="../_static/set-versions.js"></script>
<link rel="top" title="sbt Documentation" href="../index.html" />
<link rel="up" title="Detailed Topics" href="index.html" />
<link rel="next" title="Tasks" href="Tasks.html" />
<link rel="prev" title="Setup Notes" href="Setup-Notes.html" />
</head>
<body>
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li><a href="http://www.scala-sbt.org/">Home</a></li>
<li><a href="../index.html">Documentation</a></li>
<li><a href="../Getting-Started/Setup.html">Download</a></li>
<li><a href="http://groups.google.com/group/simple-build-tool">Mailing List</a></li>
<li><a href="http://github.com/sbt/sbt">Project</a></li>
</ul>
</div>
</div>
</div>
<div class="main">
<div class="container">
<div class="page-title">Task Inputs/Dependencies</div>
<div class="search-box">
<form method="get" action="http://www.google.com/search" id="search">
<input type="search" placeholder="Search 0.12.1 on Google" name="q" results="10" size="29" id="search-input">
<input type="hidden" name="sitesearch" value="http://www.scala-sbt.org/release/docs/">
<input type="submit" id="submit-search">
</form>
</div>
</div>
<div class="main-container">
<div class="container">
<div class="row">
<div class="span12">
<ul class="breadcrumb">
<li>
<span class="divider">|</span> <a href="Tasks.html">Tasks</a> <span class="divider">»</span>
</li>
<li>
<span class="divider">></span><a href="index.html">Detailed Topics</a>
</li>
<li>
<a href="../index.html">Contents</a>
</li>
<li>
<span class="divider">«</span> <a href="Setup-Notes.html">Setup Notes</a> <span class="divider">|</span>
</li>
<li>
<select id="versions"><option selected value="0.12.1">Version 0.12.1</option></select>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="span9">
<div class="section" id="task-inputs-dependencies">
<h1>Task Inputs/Dependencies<a class="headerlink" href="#task-inputs-dependencies" title="Permalink to this headline">¶</a></h1>
<p>Tasks with dependencies are now introduced in the
<a class="reference internal" href="../Getting-Started/More-About-Settings.html"><em>getting started guide</em></a>,
which you may wish to read first. This older page may have some additional detail.</p>
<p><em>Wiki Maintenance Note:</em> This page should have its overlap with the
getting started guide cleaned up, and just have any advanced or
additional notes. It should maybe also be consolidated with <a class="reference internal" href="Tasks.html"><em>Tasks</em></a>.</p>
<p>An important aspect of the task system introduced in sbt 0.10 is to
combine two common, related steps in a build:</p>
<ol class="arabic simple">
<li>Ensure some other task is performed.</li>
<li>Use some result from that task.</li>
</ol>
<p>Previous versions of sbt configured these steps separately using</p>
<ol class="arabic simple">
<li>Dependency declarations</li>
<li>Some form of shared state</li>
</ol>
<p>To see why it is advantageous to combine them, compare the situation to
that of deferring initialization of a variable in Scala. This Scala code
is a bad way to expose a value whose initialization is deferred:</p>
<div class="highlight-scala"><div class="highlight"><pre> <span class="c1">// Define a variable that will be initialized at some point</span>
<span class="c1">// We don't want to do it right away, because it might be expensive</span>
<span class="k">var</span> <span class="n">foo</span><span class="k">:</span> <span class="kt">Foo</span> <span class="o">=</span> <span class="k">_</span>
<span class="c1">// Define a function to initialize the variable</span>
<span class="k">def</span> <span class="n">makeFoo</span><span class="o">()</span><span class="k">:</span> <span class="kt">Unit</span> <span class="o">=</span> <span class="o">...</span> <span class="n">initialize</span> <span class="n">foo</span> <span class="o">...</span>
</pre></div>
</div>
<p>Typical usage would be:</p>
<div class="highlight-scala"><div class="highlight"><pre><span class="n">makeFoo</span><span class="o">()</span>
<span class="n">doSomething</span><span class="o">(</span> <span class="n">foo</span> <span class="o">)</span>
</pre></div>
</div>
<p>This example is rather exaggerated in its badness, but I claim it is
nearly the same situation as our two step task definitions. Particular
reasons this is bad include:</p>
<ol class="arabic simple">
<li>A client needs to know to call <tt class="docutils literal"><span class="pre">makeFoo()</span></tt> first.</li>
<li><tt class="docutils literal"><span class="pre">foo</span></tt> could be changed by other code. There could be a
<tt class="docutils literal"><span class="pre">def</span> <span class="pre">makeFoo2()</span></tt>, for example.</li>
<li>Access to foo is not thread safe.</li>
</ol>
<p>The first point is like declaring a task dependency, the second is like
two tasks modifying the same state (either project variables or files),
and the third is a consequence of unsynchronized, shared state.</p>
<p>In Scala, we have the built-in functionality to easily fix this:
<tt class="docutils literal"><span class="pre">lazy</span> <span class="pre">val</span></tt>.</p>
<div class="highlight-scala"><div class="highlight"><pre><span class="k">lazy</span> <span class="k">val</span> <span class="n">foo</span><span class="k">:</span> <span class="kt">Foo</span> <span class="o">=</span> <span class="o">...</span> <span class="n">initialize</span> <span class="n">foo</span> <span class="o">...</span>
</pre></div>
</div>
<p>with the example usage:</p>
<div class="highlight-scala"><div class="highlight"><pre><span class="n">doSomething</span><span class="o">(</span> <span class="n">foo</span> <span class="o">)</span>
</pre></div>
</div>
<p>Here, <tt class="docutils literal"><span class="pre">lazy</span> <span class="pre">val</span></tt> gives us thread safety, guaranteed initialization
before access, and immutability all in one, DRY construct. The task
system in sbt does the same thing for tasks (and more, but we won't go
into that here) that <tt class="docutils literal"><span class="pre">lazy</span> <span class="pre">val</span></tt> did for our bad example.</p>
<p>A task definition must declare its inputs and the type of its output.
sbt will ensure that the input tasks have run and will then provide
their results to the function that implements the task, which will
generate its own result. Other tasks can use this result and be assured
that the task has run (once) and be thread-safe and typesafe in the
process.</p>
<p>The general form of a task definition looks like:</p>
<div class="highlight-scala"><div class="highlight"><pre><span class="n">myTask</span> <span class="o"><<=</span> <span class="o">(</span><span class="n">aTask</span><span class="o">,</span> <span class="n">bTask</span><span class="o">)</span> <span class="n">map</span> <span class="o">{</span> <span class="o">(</span><span class="n">a</span><span class="k">:</span> <span class="kt">A</span><span class="o">,</span> <span class="n">b</span><span class="k">:</span> <span class="kt">B</span><span class="o">)</span> <span class="k">=></span>
<span class="o">...</span> <span class="k">do</span> <span class="n">something</span> <span class="k">with</span> <span class="n">a</span><span class="o">,</span> <span class="n">b</span> <span class="n">and</span> <span class="n">generate</span> <span class="n">a</span> <span class="n">result</span> <span class="o">...</span>
<span class="o">}</span>
</pre></div>
</div>
<p>(This is only intended to be a discussion of the ideas behind tasks, so
see the <a class="reference internal" href="Tasks.html"><em>sbt Tasks</em></a> page
for details on usage.) Basically, <tt class="docutils literal"><span class="pre">myTask</span></tt> is defined by declaring
<tt class="docutils literal"><span class="pre">aTask</span></tt> and <tt class="docutils literal"><span class="pre">bTask</span></tt> as inputs and by defining the function to apply
to the results of these tasks. Here, <tt class="docutils literal"><span class="pre">aTask</span></tt> is assumed to produce a
result of type <tt class="docutils literal"><span class="pre">A</span></tt> and <tt class="docutils literal"><span class="pre">bTask</span></tt> is assumed to produce a result of
type <tt class="docutils literal"><span class="pre">B</span></tt>.</p>
<div class="section" id="application">
<h2>Application<a class="headerlink" href="#application" title="Permalink to this headline">¶</a></h2>
<p>Apply this in practice:</p>
<ol class="arabic simple">
<li>Determine the tasks that produce the values you need</li>
<li><tt class="docutils literal"><span class="pre">map</span></tt> the tasks with the function that implements your task.</li>
</ol>
<p>As an example, consider generating a zip file containing the binary jar,
source jar, and documentation jar for your project. First, determine
what tasks produce the jars. In this case, the input tasks are
<tt class="docutils literal"><span class="pre">packageBin</span></tt>, <tt class="docutils literal"><span class="pre">packageSrc</span></tt>, and <tt class="docutils literal"><span class="pre">packageDoc</span></tt> in the main
<tt class="docutils literal"><span class="pre">Compile</span></tt> scope. The result of each of these tasks is the File for the
jar that they generated. Our zip file task is defined by mapping these
package tasks and including their outputs in a zip file. As good
practice, we then return the File for this zip so that other tasks can
map on the zip task.</p>
<div class="highlight-scala"><div class="highlight"><pre><span class="n">zip</span> <span class="o"><<=</span> <span class="o">(</span><span class="n">packageBin</span> <span class="n">in</span> <span class="nc">Compile</span><span class="o">,</span> <span class="n">packageSrc</span> <span class="n">in</span> <span class="nc">Compile</span><span class="o">,</span> <span class="n">packageDoc</span> <span class="n">in</span> <span class="nc">Compile</span><span class="o">,</span> <span class="n">zipPath</span><span class="o">)</span> <span class="n">map</span> <span class="o">{</span>
<span class="o">(</span><span class="n">bin</span><span class="k">:</span> <span class="kt">File</span><span class="o">,</span> <span class="n">src</span><span class="k">:</span> <span class="kt">File</span><span class="o">,</span> <span class="n">doc</span><span class="k">:</span> <span class="kt">File</span><span class="o">,</span> <span class="n">out</span><span class="k">:</span> <span class="kt">File</span><span class="o">)</span> <span class="k">=></span>
<span class="k">val</span> <span class="n">inputs</span><span class="k">:</span> <span class="kt">Seq</span><span class="o">[(</span><span class="kt">File</span>,<span class="kt">String</span><span class="o">)]</span> <span class="k">=</span> <span class="nc">Seq</span><span class="o">(</span><span class="n">bin</span><span class="o">,</span> <span class="n">src</span><span class="o">,</span> <span class="n">doc</span><span class="o">)</span> <span class="n">x</span> <span class="nc">Path</span><span class="o">.</span><span class="n">flat</span>
<span class="nc">IO</span><span class="o">.</span><span class="n">zip</span><span class="o">(</span><span class="n">inputs</span><span class="o">,</span> <span class="n">out</span><span class="o">)</span>
<span class="n">out</span>
<span class="o">}</span>
</pre></div>
</div>
<p>The <tt class="docutils literal"><span class="pre">val</span> <span class="pre">inputs</span></tt> line defines how the input files are mapped to paths
in the zip. See <a class="reference internal" href="Mapping-Files.html"><em>Mapping Files</em></a> for details.
The explicit types are not required, but are included for clarity.</p>
<p>The <tt class="docutils literal"><span class="pre">zipPath</span></tt> input would be a custom task to define the location of
the zip file. For example:</p>
<div class="highlight-scala"><div class="highlight"><pre><span class="n">zipPath</span> <span class="o"><<=</span> <span class="n">target</span> <span class="n">map</span> <span class="o">{</span>
<span class="o">(</span><span class="n">t</span><span class="k">:</span> <span class="kt">File</span><span class="o">)</span> <span class="k">=></span>
<span class="n">t</span> <span class="o">/</span> <span class="s">"out.zip"</span>
<span class="o">}</span>
</pre></div>
</div>
</div>
</div>
</div>
<div class="span3"><p class="contents-title">Contents</p>
<div id="scroller-anchor">
<div id="scroller">
<div id="toc"><ul>
<li><a class="reference internal" href="#">Task Inputs/Dependencies</a><ul>
<li><a class="reference internal" href="#application">Application</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div></div>
</div>
</div>
</div>
</div>
</body>
</html>