summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmmonite Travis Bot <haoyi.sg+travis@gmail.com>2019-09-24 12:25:17 +0000
committerAmmonite Travis Bot <haoyi.sg+travis@gmail.com>2019-09-24 12:25:17 +0000
commitb9b2806c1faf208d96cfe9c610e5461ec0e74471 (patch)
treed8410149c6622b1f664a7c703b86eb4431cc67f5
downloadmill-gh-pages.tar.gz
mill-gh-pages.tar.bz2
mill-gh-pages.zip
first commitgh-pages
-rw-r--r--VisualizeCompile.svg361
-rw-r--r--VisualizeCore.svg805
-rw-r--r--VisualizePlan.svg355
-rw-r--r--example-1.zipbin0 -> 1039 bytes
-rw-r--r--example-2.zipbin0 -> 1219 bytes
-rw-r--r--favicon.icobin0 -> 206 bytes
-rw-r--r--index.html628
-rw-r--r--logo-white.svg1
-rw-r--r--page/common-project-layouts.html355
-rw-r--r--page/configuring-mill.html447
-rw-r--r--page/contrib-modules.html649
-rw-r--r--page/cross-builds.html220
-rw-r--r--page/extending-mill.html210
-rw-r--r--page/mill-internals.html264
-rw-r--r--page/modules.html221
-rw-r--r--page/tasks.html324
-rw-r--r--page/thirdparty-modules.html351
17 files changed, 5191 insertions, 0 deletions
diff --git a/VisualizeCompile.svg b/VisualizeCompile.svg
new file mode 100644
index 00000000..a74cdb42
--- /dev/null
+++ b/VisualizeCompile.svg
@@ -0,0 +1,361 @@
+<svg width="2439pt" height="476pt"
+ viewBox="0.00 0.00 2439.44 476.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 472)">
+<title>example1</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-472 2435.4446,-472 2435.4446,4 -4,4"/>
+<!-- moduledefs.compile -->
+<g id="node1" class="node">
+<title>moduledefs.compile</title>
+<ellipse fill="none" stroke="#000000" cx="769.8174" cy="-18" rx="89.7283" ry="18"/>
+<text text-anchor="middle" x="769.8174" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.compile</text>
+</g>
+<!-- main.client.compile -->
+<g id="node2" class="node">
+<title>main.client.compile</title>
+<ellipse fill="none" stroke="#000000" cx="945.8174" cy="-90" rx="87.9781" ry="18"/>
+<text text-anchor="middle" x="945.8174" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">main.client.compile</text>
+</g>
+<!-- testng.compile -->
+<g id="node3" class="node">
+<title>testng.compile</title>
+<ellipse fill="none" stroke="#000000" cx="2363.8174" cy="-450" rx="67.7546" ry="18"/>
+<text text-anchor="middle" x="2363.8174" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">testng.compile</text>
+</g>
+<!-- core.compile -->
+<g id="node4" class="node">
+<title>core.compile</title>
+<ellipse fill="none" stroke="#000000" cx="769.8174" cy="-90" rx="61.3551" ry="18"/>
+<text text-anchor="middle" x="769.8174" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.compile</text>
+</g>
+<!-- core.compile&#45;&gt;moduledefs.compile -->
+<g id="edge1" class="edge">
+<title>core.compile&#45;&gt;moduledefs.compile</title>
+<path fill="none" stroke="#000000" d="M769.8174,-71.8314C769.8174,-64.131 769.8174,-54.9743 769.8174,-46.4166"/>
+<polygon fill="#000000" stroke="#000000" points="773.3175,-46.4132 769.8174,-36.4133 766.3175,-46.4133 773.3175,-46.4132"/>
+</g>
+<!-- main.compile -->
+<g id="node5" class="node">
+<title>main.compile</title>
+<ellipse fill="none" stroke="#000000" cx="769.8174" cy="-162" rx="63.7434" ry="18"/>
+<text text-anchor="middle" x="769.8174" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">main.compile</text>
+</g>
+<!-- main.compile&#45;&gt;main.client.compile -->
+<g id="edge3" class="edge">
+<title>main.compile&#45;&gt;main.client.compile</title>
+<path fill="none" stroke="#000000" d="M806.2847,-147.0816C832.5183,-136.3496 868.1856,-121.7584 896.892,-110.0149"/>
+<polygon fill="#000000" stroke="#000000" points="898.4065,-113.177 906.3367,-106.1512 895.756,-106.6982 898.4065,-113.177"/>
+</g>
+<!-- main.compile&#45;&gt;core.compile -->
+<g id="edge2" class="edge">
+<title>main.compile&#45;&gt;core.compile</title>
+<path fill="none" stroke="#000000" d="M769.8174,-143.8314C769.8174,-136.131 769.8174,-126.9743 769.8174,-118.4166"/>
+<polygon fill="#000000" stroke="#000000" points="773.3175,-118.4132 769.8174,-108.4133 766.3175,-118.4133 773.3175,-118.4132"/>
+</g>
+<!-- main.test.compile -->
+<g id="node6" class="node">
+<title>main.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="703.8174" cy="-306" rx="79.8914" ry="18"/>
+<text text-anchor="middle" x="703.8174" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">main.test.compile</text>
+</g>
+<!-- main.test.compile&#45;&gt;main.compile -->
+<g id="edge4" class="edge">
+<title>main.test.compile&#45;&gt;main.compile</title>
+<path fill="none" stroke="#000000" d="M711.9531,-288.0556C720.2028,-269.88 733.3521,-240.965 744.8174,-216 748.8272,-207.2689 753.2229,-197.755 757.195,-189.1792"/>
+<polygon fill="#000000" stroke="#000000" points="760.4257,-190.5319 761.4565,-179.9873 754.075,-187.5876 760.4257,-190.5319"/>
+</g>
+<!-- main.client.test.compile -->
+<g id="node7" class="node">
+<title>main.client.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="954.8174" cy="-162" rx="103.6252" ry="18"/>
+<text text-anchor="middle" x="954.8174" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">main.client.test.compile</text>
+</g>
+<!-- main.client.test.compile&#45;&gt;main.client.compile -->
+<g id="edge5" class="edge">
+<title>main.client.test.compile&#45;&gt;main.client.compile</title>
+<path fill="none" stroke="#000000" d="M952.5463,-143.8314C951.5838,-136.131 950.4392,-126.9743 949.3695,-118.4166"/>
+<polygon fill="#000000" stroke="#000000" points="952.8325,-117.9019 948.1191,-108.4133 945.8865,-118.7702 952.8325,-117.9019"/>
+</g>
+<!-- scalalib.compile -->
+<g id="node8" class="node">
+<title>scalalib.compile</title>
+<ellipse fill="none" stroke="#000000" cx="827.8174" cy="-234" rx="74.1116" ry="18"/>
+<text text-anchor="middle" x="827.8174" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalalib.compile</text>
+</g>
+<!-- scalalib.compile&#45;&gt;main.compile -->
+<g id="edge6" class="edge">
+<title>scalalib.compile&#45;&gt;main.compile</title>
+<path fill="none" stroke="#000000" d="M813.4803,-216.2022C806.5269,-207.5704 798.0472,-197.0439 790.4168,-187.5717"/>
+<polygon fill="#000000" stroke="#000000" points="792.9885,-185.1849 783.9896,-179.593 787.5373,-189.5763 792.9885,-185.1849"/>
+</g>
+<!-- main.graphviz.compile -->
+<g id="node9" class="node">
+<title>main.graphviz.compile</title>
+<ellipse fill="none" stroke="#000000" cx="449.8174" cy="-306" rx="100.1433" ry="18"/>
+<text text-anchor="middle" x="449.8174" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">main.graphviz.compile</text>
+</g>
+<!-- main.graphviz.compile&#45;&gt;scalalib.compile -->
+<g id="edge7" class="edge">
+<title>main.graphviz.compile&#45;&gt;scalalib.compile</title>
+<path fill="none" stroke="#000000" d="M518.7089,-292.8778C586.9675,-279.8762 690.9147,-260.0767 759.1093,-247.0873"/>
+<polygon fill="#000000" stroke="#000000" points="760.1508,-250.4519 769.3192,-245.1425 758.8409,-243.5755 760.1508,-250.4519"/>
+</g>
+<!-- main.graphviz.test.compile -->
+<g id="node10" class="node">
+<title>main.graphviz.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="311.8174" cy="-378" rx="115.791" ry="18"/>
+<text text-anchor="middle" x="311.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">main.graphviz.test.compile</text>
+</g>
+<!-- main.graphviz.test.compile&#45;&gt;main.test.compile -->
+<g id="edge9" class="edge">
+<title>main.graphviz.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M386.9351,-364.2029C457.4949,-351.2429 562.3458,-331.9846 631.8587,-319.2169"/>
+<polygon fill="#000000" stroke="#000000" points="632.6469,-322.6308 641.85,-317.3818 631.3823,-315.7459 632.6469,-322.6308"/>
+</g>
+<!-- main.graphviz.test.compile&#45;&gt;main.graphviz.compile -->
+<g id="edge8" class="edge">
+<title>main.graphviz.test.compile&#45;&gt;main.graphviz.compile</title>
+<path fill="none" stroke="#000000" d="M345.2234,-360.5708C364.1771,-350.6819 388.0652,-338.2185 408.2258,-327.7"/>
+<polygon fill="#000000" stroke="#000000" points="409.9484,-330.749 417.1953,-323.0202 406.7104,-324.5429 409.9484,-330.749"/>
+</g>
+<!-- scalalib.test.compile -->
+<g id="node11" class="node">
+<title>scalalib.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="859.8174" cy="-378" rx="89.7595" ry="18"/>
+<text text-anchor="middle" x="859.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalalib.test.compile</text>
+</g>
+<!-- scalalib.test.compile&#45;&gt;main.test.compile -->
+<g id="edge11" class="edge">
+<title>scalalib.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M824.0279,-361.4817C801.4747,-351.0726 772.1839,-337.5538 748.1623,-326.4669"/>
+<polygon fill="#000000" stroke="#000000" points="749.4491,-323.206 738.9028,-322.1933 746.5157,-329.5618 749.4491,-323.206"/>
+</g>
+<!-- scalalib.test.compile&#45;&gt;scalalib.compile -->
+<g id="edge10" class="edge">
+<title>scalalib.test.compile&#45;&gt;scalalib.compile</title>
+<path fill="none" stroke="#000000" d="M855.7646,-359.7623C850.2825,-335.0928 840.4529,-290.8598 834.0336,-261.9731"/>
+<polygon fill="#000000" stroke="#000000" points="837.4234,-261.0922 831.8373,-252.0896 830.59,-262.6108 837.4234,-261.0922"/>
+</g>
+<!-- scalalib.worker.compile -->
+<g id="node12" class="node">
+<title>scalalib.worker.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1027.8174" cy="-306" rx="103.6296" ry="18"/>
+<text text-anchor="middle" x="1027.8174" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalalib.worker.compile</text>
+</g>
+<!-- scalalib.worker.compile&#45;&gt;scalalib.compile -->
+<g id="edge12" class="edge">
+<title>scalalib.worker.compile&#45;&gt;scalalib.compile</title>
+<path fill="none" stroke="#000000" d="M982.4343,-289.6621C951.6227,-278.5699 910.8323,-263.8854 878.8846,-252.3842"/>
+<polygon fill="#000000" stroke="#000000" points="879.869,-249.0187 869.2746,-248.9246 877.4979,-255.605 879.869,-249.0187"/>
+</g>
+<!-- scalalib.worker.test.compile -->
+<g id="node13" class="node">
+<title>scalalib.worker.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1087.8174" cy="-378" rx="119.7772" ry="18"/>
+<text text-anchor="middle" x="1087.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalalib.worker.test.compile</text>
+</g>
+<!-- scalalib.worker.test.compile&#45;&gt;main.test.compile -->
+<g id="edge14" class="edge">
+<title>scalalib.worker.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M1012.8668,-363.9468C944.1491,-351.0622 843.0839,-332.1125 775.4371,-319.4287"/>
+<polygon fill="#000000" stroke="#000000" points="775.7661,-315.9295 765.2923,-317.5266 774.476,-322.8096 775.7661,-315.9295"/>
+</g>
+<!-- scalalib.worker.test.compile&#45;&gt;scalalib.worker.compile -->
+<g id="edge13" class="edge">
+<title>scalalib.worker.test.compile&#45;&gt;scalalib.worker.compile</title>
+<path fill="none" stroke="#000000" d="M1072.6769,-359.8314C1065.5883,-351.3251 1057.019,-341.0419 1049.2774,-331.752"/>
+<polygon fill="#000000" stroke="#000000" points="1051.8359,-329.355 1042.7452,-323.9134 1046.4583,-333.8363 1051.8359,-329.355"/>
+</g>
+<!-- core.test.compile -->
+<g id="node14" class="node">
+<title>core.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="560.8174" cy="-378" rx="77.0023" ry="18"/>
+<text text-anchor="middle" x="560.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.test.compile</text>
+</g>
+<!-- core.test.compile&#45;&gt;main.test.compile -->
+<g id="edge15" class="edge">
+<title>core.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M593.2663,-361.6621C613.5996,-351.4244 640.0109,-338.1264 661.9192,-327.0956"/>
+<polygon fill="#000000" stroke="#000000" points="663.6442,-330.1458 671.0019,-322.5225 660.4961,-323.8935 663.6442,-330.1458"/>
+</g>
+<!-- scalajslib.compile -->
+<g id="node15" class="node">
+<title>scalajslib.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1692.8174" cy="-306" rx="80.4901" ry="18"/>
+<text text-anchor="middle" x="1692.8174" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalajslib.compile</text>
+</g>
+<!-- scalajslib.compile&#45;&gt;scalalib.compile -->
+<g id="edge16" class="edge">
+<title>scalajslib.compile&#45;&gt;scalalib.compile</title>
+<path fill="none" stroke="#000000" d="M1617.1904,-299.705C1454.9005,-286.1965 1074.508,-254.5338 908.1202,-240.6842"/>
+<polygon fill="#000000" stroke="#000000" points="908.2104,-237.1797 897.9545,-239.838 907.6297,-244.1555 908.2104,-237.1797"/>
+</g>
+<!-- dev.compile -->
+<g id="node16" class="node">
+<title>dev.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1976.8174" cy="-378" rx="58.5085" ry="18"/>
+<text text-anchor="middle" x="1976.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">dev.compile</text>
+</g>
+<!-- dev.compile&#45;&gt;scalajslib.compile -->
+<g id="edge17" class="edge">
+<title>dev.compile&#45;&gt;scalajslib.compile</title>
+<path fill="none" stroke="#000000" d="M1932.5805,-366.1957C1924.6723,-364.1124 1916.5048,-361.9783 1908.8174,-360 1857.7654,-346.8623 1799.8072,-332.3973 1756.7891,-321.7475"/>
+<polygon fill="#000000" stroke="#000000" points="1757.5666,-318.3344 1747.0188,-319.3307 1755.8857,-325.1296 1757.5666,-318.3344"/>
+</g>
+<!-- dev.test.compile -->
+<g id="node17" class="node">
+<title>dev.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1817.8174" cy="-450" rx="74.1566" ry="18"/>
+<text text-anchor="middle" x="1817.8174" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">dev.test.compile</text>
+</g>
+<!-- dev.test.compile&#45;&gt;main.test.compile -->
+<g id="edge19" class="edge">
+<title>dev.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M1748.6515,-443.3587C1707.2477,-439.5749 1653.5577,-435.004 1605.8174,-432 1557.095,-428.9342 765.9126,-426.5291 727.8174,-396 709.657,-381.4465 704.3302,-354.8133 703.147,-334.2813"/>
+<polygon fill="#000000" stroke="#000000" points="706.6431,-334.0932 702.8599,-324.1969 699.646,-334.2924 706.6431,-334.0932"/>
+</g>
+<!-- dev.test.compile&#45;&gt;dev.compile -->
+<g id="edge18" class="edge">
+<title>dev.test.compile&#45;&gt;dev.compile</title>
+<path fill="none" stroke="#000000" d="M1853.1047,-434.0209C1877.1178,-423.147 1909.022,-408.6998 1934.4163,-397.2005"/>
+<polygon fill="#000000" stroke="#000000" points="1936.1344,-400.2647 1943.8001,-392.9512 1933.2468,-393.888 1936.1344,-400.2647"/>
+</g>
+<!-- scalajslib.test.compile -->
+<g id="node18" class="node">
+<title>scalajslib.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1321.8174" cy="-378" rx="96.1382" ry="18"/>
+<text text-anchor="middle" x="1321.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalajslib.test.compile</text>
+</g>
+<!-- scalajslib.test.compile&#45;&gt;main.test.compile -->
+<g id="edge21" class="edge">
+<title>scalajslib.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M1252.4455,-365.4537C1240.5799,-363.4952 1228.3596,-361.5951 1216.8174,-360 1066.727,-339.2579 890.9548,-322.3462 789.0039,-313.2618"/>
+<polygon fill="#000000" stroke="#000000" points="789.0353,-309.7509 778.7651,-312.3536 788.4168,-316.7235 789.0353,-309.7509"/>
+</g>
+<!-- scalajslib.test.compile&#45;&gt;scalajslib.compile -->
+<g id="edge20" class="edge">
+<title>scalajslib.test.compile&#45;&gt;scalajslib.compile</title>
+<path fill="none" stroke="#000000" d="M1389.0027,-364.9613C1454.8441,-352.1835 1554.816,-332.7819 1621.9086,-319.7613"/>
+<polygon fill="#000000" stroke="#000000" points="1622.8222,-323.1494 1631.9722,-317.8082 1621.4885,-316.2776 1622.8222,-323.1494"/>
+</g>
+<!-- scalajslib.worker[0.6].compile -->
+<g id="node19" class="node">
+<title>scalajslib.worker[0.6].compile</title>
+<ellipse fill="none" stroke="#000000" cx="1572.8174" cy="-378" rx="136.0514" ry="18"/>
+<text text-anchor="middle" x="1572.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalajslib.worker[0.6].compile</text>
+</g>
+<!-- scalajslib.worker[0.6].compile&#45;&gt;scalajslib.compile -->
+<g id="edge22" class="edge">
+<title>scalajslib.worker[0.6].compile&#45;&gt;scalajslib.compile</title>
+<path fill="none" stroke="#000000" d="M1602.1727,-360.3868C1618.3625,-350.6729 1638.6214,-338.5176 1655.8783,-328.1634"/>
+<polygon fill="#000000" stroke="#000000" points="1657.8173,-331.0818 1664.5915,-322.9355 1654.2158,-325.0793 1657.8173,-331.0818"/>
+</g>
+<!-- scalajslib.worker[0.6].test.compile -->
+<g id="node20" class="node">
+<title>scalajslib.worker[0.6].test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="966.8174" cy="-450" rx="152.1988" ry="18"/>
+<text text-anchor="middle" x="966.8174" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalajslib.worker[0.6].test.compile</text>
+</g>
+<!-- scalajslib.worker[0.6].test.compile&#45;&gt;main.test.compile -->
+<g id="edge24" class="edge">
+<title>scalajslib.worker[0.6].test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M823.6978,-443.8679C686.8403,-436.4969 497.9192,-421.776 474.8174,-396 464.1387,-384.0851 464.8865,-372.545 474.8174,-360 493.062,-336.9528 563.1727,-322.7521 621.0644,-314.7355"/>
+<polygon fill="#000000" stroke="#000000" points="621.5308,-318.2043 630.9766,-313.4057 620.6,-311.2665 621.5308,-318.2043"/>
+</g>
+<!-- scalajslib.worker[0.6].test.compile&#45;&gt;scalajslib.worker[0.6].compile -->
+<g id="edge23" class="edge">
+<title>scalajslib.worker[0.6].test.compile&#45;&gt;scalajslib.worker[0.6].compile</title>
+<path fill="none" stroke="#000000" d="M1075.5811,-437.4125C1168.8049,-426.5803 1306.6679,-410.4586 1426.8174,-396 1438.6041,-394.5816 1450.9241,-393.0848 1463.1952,-391.5849"/>
+<polygon fill="#000000" stroke="#000000" points="1463.978,-395.0153 1473.4785,-390.3259 1463.1273,-388.0672 1463.978,-395.0153"/>
+</g>
+<!-- scalajslib.worker[1.0].compile -->
+<g id="node21" class="node">
+<title>scalajslib.worker[1.0].compile</title>
+<ellipse fill="none" stroke="#000000" cx="2189.8174" cy="-378" rx="136.0514" ry="18"/>
+<text text-anchor="middle" x="2189.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalajslib.worker[1.0].compile</text>
+</g>
+<!-- scalajslib.worker[1.0].compile&#45;&gt;scalajslib.compile -->
+<g id="edge25" class="edge">
+<title>scalajslib.worker[1.0].compile&#45;&gt;scalajslib.compile</title>
+<path fill="none" stroke="#000000" d="M2097.7907,-364.6682C2003.6304,-351.0272 1858.9378,-330.0657 1770.3982,-317.2391"/>
+<polygon fill="#000000" stroke="#000000" points="1770.8162,-313.7632 1760.4177,-315.7932 1769.8125,-320.6908 1770.8162,-313.7632"/>
+</g>
+<!-- scalajslib.worker[1.0].test.compile -->
+<g id="node22" class="node">
+<title>scalajslib.worker[1.0].test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="2125.8174" cy="-450" rx="152.1988" ry="18"/>
+<text text-anchor="middle" x="2125.8174" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">scalajslib.worker[1.0].test.compile</text>
+</g>
+<!-- scalajslib.worker[1.0].test.compile&#45;&gt;main.test.compile -->
+<g id="edge27" class="edge">
+<title>scalajslib.worker[1.0].test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M2004.1561,-439.1879C1970.6876,-436.5078 1934.3684,-433.8707 1900.8174,-432 1837.5508,-428.4724 815.8414,-427.4241 760.8174,-396 748.2695,-388.8339 729.8034,-356.885 717.3187,-333.077"/>
+<polygon fill="#000000" stroke="#000000" points="720.3851,-331.3869 712.6909,-324.1033 714.1637,-334.5953 720.3851,-331.3869"/>
+</g>
+<!-- scalajslib.worker[1.0].test.compile&#45;&gt;scalajslib.worker[1.0].compile -->
+<g id="edge26" class="edge">
+<title>scalajslib.worker[1.0].test.compile&#45;&gt;scalajslib.worker[1.0].compile</title>
+<path fill="none" stroke="#000000" d="M2141.9673,-431.8314C2149.6048,-423.2392 2158.8538,-412.834 2167.1767,-403.4708"/>
+<polygon fill="#000000" stroke="#000000" points="2169.8666,-405.7128 2173.8944,-395.9134 2164.6348,-401.0622 2169.8666,-405.7128"/>
+</g>
+<!-- twirllib.compile -->
+<g id="node23" class="node">
+<title>twirllib.compile</title>
+<ellipse fill="none" stroke="#000000" cx="145.8174" cy="-306" rx="72.9871" ry="18"/>
+<text text-anchor="middle" x="145.8174" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">twirllib.compile</text>
+</g>
+<!-- twirllib.compile&#45;&gt;scalalib.compile -->
+<g id="edge28" class="edge">
+<title>twirllib.compile&#45;&gt;scalalib.compile</title>
+<path fill="none" stroke="#000000" d="M213.0767,-298.8993C340.072,-285.4922 614.4994,-256.5204 749.5358,-242.2643"/>
+<polygon fill="#000000" stroke="#000000" points="750.2237,-245.7113 759.8009,-241.1806 749.4887,-238.7499 750.2237,-245.7113"/>
+</g>
+<!-- twirllib.test.compile -->
+<g id="node24" class="node">
+<title>twirllib.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="88.8174" cy="-378" rx="88.6352" ry="18"/>
+<text text-anchor="middle" x="88.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">twirllib.test.compile</text>
+</g>
+<!-- twirllib.test.compile&#45;&gt;main.test.compile -->
+<g id="edge30" class="edge">
+<title>twirllib.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M152.7394,-365.4484C164.0648,-363.4565 175.7676,-361.5466 186.8174,-360 351.3196,-336.9755 393.7154,-342.2331 558.8174,-324 580.1485,-321.6443 603.2167,-318.8797 624.5444,-316.2339"/>
+<polygon fill="#000000" stroke="#000000" points="625.0429,-319.6989 634.5326,-314.9878 624.1762,-312.7527 625.0429,-319.6989"/>
+</g>
+<!-- twirllib.test.compile&#45;&gt;twirllib.compile -->
+<g id="edge29" class="edge">
+<title>twirllib.test.compile&#45;&gt;twirllib.compile</title>
+<path fill="none" stroke="#000000" d="M102.9073,-360.2022C109.6898,-351.6348 117.95,-341.2009 125.4051,-331.7839"/>
+<polygon fill="#000000" stroke="#000000" points="128.2292,-333.8555 131.6921,-323.8425 122.7408,-329.5106 128.2292,-333.8555"/>
+</g>
+<!-- integration.compile -->
+<g id="node25" class="node">
+<title>integration.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1813.8174" cy="-378" rx="86.2949" ry="18"/>
+<text text-anchor="middle" x="1813.8174" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">integration.compile</text>
+</g>
+<!-- integration.compile&#45;&gt;scalajslib.compile -->
+<g id="edge31" class="edge">
+<title>integration.compile&#45;&gt;scalajslib.compile</title>
+<path fill="none" stroke="#000000" d="M1785.1421,-360.937C1768.7168,-351.1633 1747.9165,-338.7863 1730.2191,-328.2555"/>
+<polygon fill="#000000" stroke="#000000" points="1731.6703,-325.0464 1721.2869,-322.9405 1728.0908,-331.0619 1731.6703,-325.0464"/>
+</g>
+<!-- integration.test.compile -->
+<g id="node26" class="node">
+<title>integration.test.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1494.8174" cy="-450" rx="102.443" ry="18"/>
+<text text-anchor="middle" x="1494.8174" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">integration.test.compile</text>
+</g>
+<!-- integration.test.compile&#45;&gt;main.test.compile -->
+<g id="edge33" class="edge">
+<title>integration.test.compile&#45;&gt;main.test.compile</title>
+<path fill="none" stroke="#000000" d="M1396.2345,-445.1341C1183.9625,-434.4251 701.7467,-408.7563 689.8174,-396 674.3166,-379.4246 680.5955,-353.1485 689.106,-333.2576"/>
+<polygon fill="#000000" stroke="#000000" points="692.3325,-334.6196 693.3774,-324.0764 685.9858,-331.6668 692.3325,-334.6196"/>
+</g>
+<!-- integration.test.compile&#45;&gt;integration.compile -->
+<g id="edge32" class="edge">
+<title>integration.test.compile&#45;&gt;integration.compile</title>
+<path fill="none" stroke="#000000" d="M1557.8415,-435.7751C1611.8837,-423.5775 1689.5947,-406.0377 1745.1949,-393.4885"/>
+<polygon fill="#000000" stroke="#000000" points="1745.9768,-396.9001 1754.9608,-391.2842 1744.4356,-390.0719 1745.9768,-396.9001"/>
+</g>
+</g>
+</svg>
diff --git a/VisualizeCore.svg b/VisualizeCore.svg
new file mode 100644
index 00000000..272fe080
--- /dev/null
+++ b/VisualizeCore.svg
@@ -0,0 +1,805 @@
+<svg width="3257pt" height="476pt"
+ viewBox="0.00 0.00 3257.17 476.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 472)">
+<title>example1</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-472 3253.1744,-472 3253.1744,4 -4,4"/>
+<!-- core.scalaVersion -->
+<g id="node1" class="node">
+<title>core.scalaVersion</title>
+<ellipse fill="none" stroke="#000000" cx="1488.2502" cy="-18" rx="79.8719" ry="18"/>
+<text text-anchor="middle" x="1488.2502" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalaVersion</text>
+</g>
+<!-- core.sources -->
+<g id="node2" class="node">
+<title>core.sources</title>
+<ellipse fill="none" stroke="#000000" cx="587.2502" cy="-18" rx="59.0476" ry="18"/>
+<text text-anchor="middle" x="587.2502" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.sources</text>
+</g>
+<!-- core.generatedSources -->
+<g id="node3" class="node">
+<title>core.generatedSources</title>
+<ellipse fill="none" stroke="#000000" cx="762.2502" cy="-18" rx="98.3348" ry="18"/>
+<text text-anchor="middle" x="762.2502" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.generatedSources</text>
+</g>
+<!-- core.platformSuffix -->
+<g id="node4" class="node">
+<title>core.platformSuffix</title>
+<ellipse fill="none" stroke="#000000" cx="1698.2502" cy="-90" rx="87.4174" ry="18"/>
+<text text-anchor="middle" x="1698.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.platformSuffix</text>
+</g>
+<!-- core.transitiveLocalClasspath -->
+<g id="node5" class="node">
+<title>core.transitiveLocalClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2833.2502" cy="-90" rx="125.5739" ry="18"/>
+<text text-anchor="middle" x="2833.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.transitiveLocalClasspath</text>
+</g>
+<!-- core.resources -->
+<g id="node6" class="node">
+<title>core.resources</title>
+<ellipse fill="none" stroke="#000000" cx="1488.2502" cy="-90" rx="66.5506" ry="18"/>
+<text text-anchor="middle" x="1488.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.resources</text>
+</g>
+<!-- core.unmanagedClasspath -->
+<g id="node7" class="node">
+<title>core.unmanagedClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2337.2502" cy="-90" rx="112.2626" ry="18"/>
+<text text-anchor="middle" x="2337.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.unmanagedClasspath</text>
+</g>
+<!-- core.ivyDeps -->
+<g id="node8" class="node">
+<title>core.ivyDeps</title>
+<ellipse fill="none" stroke="#000000" cx="62.2502" cy="-18" rx="62.0014" ry="18"/>
+<text text-anchor="middle" x="62.2502" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.ivyDeps</text>
+</g>
+<!-- core.scalacOptions -->
+<g id="node9" class="node">
+<title>core.scalacOptions</title>
+<ellipse fill="none" stroke="#000000" cx="899.2502" cy="-162" rx="84.4671" ry="18"/>
+<text text-anchor="middle" x="899.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalacOptions</text>
+</g>
+<!-- core.scalacPluginIvyDeps -->
+<g id="node10" class="node">
+<title>core.scalacPluginIvyDeps</title>
+<ellipse fill="none" stroke="#000000" cx="1215.2502" cy="-90" rx="111.677" ry="18"/>
+<text text-anchor="middle" x="1215.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalacPluginIvyDeps</text>
+</g>
+<!-- core.javacOptions -->
+<g id="node11" class="node">
+<title>core.javacOptions</title>
+<ellipse fill="none" stroke="#000000" cx="2306.2502" cy="-162" rx="81.0388" ry="18"/>
+<text text-anchor="middle" x="2306.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.javacOptions</text>
+</g>
+<!-- core.upstreamCompileOutput -->
+<g id="node12" class="node">
+<title>core.upstreamCompileOutput</title>
+<ellipse fill="none" stroke="#000000" cx="2531.2502" cy="-162" rx="125.6029" ry="18"/>
+<text text-anchor="middle" x="2531.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.upstreamCompileOutput</text>
+</g>
+<!-- core.mainClass -->
+<g id="node13" class="node">
+<title>core.mainClass</title>
+<ellipse fill="none" stroke="#000000" cx="2692.2502" cy="-234" rx="70.101" ry="18"/>
+<text text-anchor="middle" x="2692.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.mainClass</text>
+</g>
+<!-- core.artifactName -->
+<g id="node14" class="node">
+<title>core.artifactName</title>
+<ellipse fill="none" stroke="#000000" cx="346.2502" cy="-162" rx="80.4302" ry="18"/>
+<text text-anchor="middle" x="346.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.artifactName</text>
+</g>
+<!-- core.crossFullScalaVersion -->
+<g id="node15" class="node">
+<title>core.crossFullScalaVersion</title>
+<ellipse fill="none" stroke="#000000" cx="995.2502" cy="-18" rx="116.9078" ry="18"/>
+<text text-anchor="middle" x="995.2502" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.crossFullScalaVersion</text>
+</g>
+<!-- core.publishVersion -->
+<g id="node16" class="node">
+<title>core.publishVersion</title>
+<ellipse fill="none" stroke="#000000" cx="179.2502" cy="-234" rx="89.1467" ry="18"/>
+<text text-anchor="middle" x="179.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.publishVersion</text>
+</g>
+<!-- core.runIvyDeps -->
+<g id="node17" class="node">
+<title>core.runIvyDeps</title>
+<ellipse fill="none" stroke="#000000" cx="3052.2502" cy="-90" rx="75.8064" ry="18"/>
+<text text-anchor="middle" x="3052.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.runIvyDeps</text>
+</g>
+<!-- core.forkArgs -->
+<g id="node18" class="node">
+<title>core.forkArgs</title>
+<ellipse fill="none" stroke="#000000" cx="3184.2502" cy="-234" rx="64.8485" ry="18"/>
+<text text-anchor="middle" x="3184.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.forkArgs</text>
+</g>
+<!-- core.forkEnv -->
+<g id="node19" class="node">
+<title>core.forkEnv</title>
+<ellipse fill="none" stroke="#000000" cx="2752.2502" cy="-450" rx="61.9214" ry="18"/>
+<text text-anchor="middle" x="2752.2502" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.forkEnv</text>
+</g>
+<!-- core.testArgs -->
+<g id="node20" class="node">
+<title>core.testArgs</title>
+<ellipse fill="none" stroke="#000000" cx="2894.2502" cy="-450" rx="62.4956" ry="18"/>
+<text text-anchor="middle" x="2894.2502" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.testArgs</text>
+</g>
+<!-- core.allSources -->
+<g id="node21" class="node">
+<title>core.allSources</title>
+<ellipse fill="none" stroke="#000000" cx="762.2502" cy="-90" rx="70.0817" ry="18"/>
+<text text-anchor="middle" x="762.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.allSources</text>
+</g>
+<!-- core.allSources&#45;&gt;core.sources -->
+<g id="edge1" class="edge">
+<title>core.allSources&#45;&gt;core.sources</title>
+<path fill="none" stroke="#000000" d="M724.7083,-74.5542C697.5487,-63.38 660.7319,-48.2325 632.0363,-36.4263"/>
+<polygon fill="#000000" stroke="#000000" points="633.2214,-33.1293 622.6418,-32.5611 630.558,-39.6028 633.2214,-33.1293"/>
+</g>
+<!-- core.allSources&#45;&gt;core.generatedSources -->
+<g id="edge2" class="edge">
+<title>core.allSources&#45;&gt;core.generatedSources</title>
+<path fill="none" stroke="#000000" d="M762.2502,-71.8314C762.2502,-64.131 762.2502,-54.9743 762.2502,-46.4166"/>
+<polygon fill="#000000" stroke="#000000" points="765.7503,-46.4132 762.2502,-36.4133 758.7503,-46.4133 765.7503,-46.4132"/>
+</g>
+<!-- core.allSourceFiles -->
+<g id="node22" class="node">
+<title>core.allSourceFiles</title>
+<ellipse fill="none" stroke="#000000" cx="1087.2502" cy="-162" rx="85.1262" ry="18"/>
+<text text-anchor="middle" x="1087.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.allSourceFiles</text>
+</g>
+<!-- core.allSourceFiles&#45;&gt;core.allSources -->
+<g id="edge3" class="edge">
+<title>core.allSourceFiles&#45;&gt;core.allSources</title>
+<path fill="none" stroke="#000000" d="M1028.3951,-148.9613C971.0727,-136.2622 884.2187,-117.0207 825.4565,-104.0026"/>
+<polygon fill="#000000" stroke="#000000" points="826.0716,-100.5541 815.5513,-101.8082 824.5575,-107.3884 826.0716,-100.5541"/>
+</g>
+<!-- core.scalaCompilerBridgeSources -->
+<g id="node23" class="node">
+<title>core.scalaCompilerBridgeSources</title>
+<ellipse fill="none" stroke="#000000" cx="1849.2502" cy="-162" rx="142.8931" ry="18"/>
+<text text-anchor="middle" x="1849.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalaCompilerBridgeSources</text>
+</g>
+<!-- core.scalaCompilerBridgeSources&#45;&gt;core.scalaVersion -->
+<g id="edge4" class="edge">
+<title>core.scalaCompilerBridgeSources&#45;&gt;core.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M1737.8174,-150.7445C1693.7223,-143.0101 1643.7614,-129.9717 1602.2502,-108 1581.6883,-97.1167 1582.2214,-86.774 1564.2502,-72 1551.1218,-61.2073 1535.9775,-50.1836 1522.6794,-40.9341"/>
+<polygon fill="#000000" stroke="#000000" points="1524.4694,-37.9173 1514.2471,-35.1324 1520.5015,-43.6841 1524.4694,-37.9173"/>
+</g>
+<!-- core.scalaCompilerBridgeSources&#45;&gt;core.platformSuffix -->
+<g id="edge5" class="edge">
+<title>core.scalaCompilerBridgeSources&#45;&gt;core.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M1812.6973,-144.5708C1791.4657,-134.4471 1764.5755,-121.6253 1742.1959,-110.9542"/>
+<polygon fill="#000000" stroke="#000000" points="1743.4432,-107.6715 1732.9104,-106.5267 1740.4304,-113.99 1743.4432,-107.6715"/>
+</g>
+<!-- core.compileIvyDeps -->
+<g id="node24" class="node">
+<title>core.compileIvyDeps</title>
+<ellipse fill="none" stroke="#000000" cx="1897.2502" cy="-90" rx="93.7824" ry="18"/>
+<text text-anchor="middle" x="1897.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.compileIvyDeps</text>
+</g>
+<!-- core.compileIvyDeps&#45;&gt;core.scalaVersion -->
+<g id="edge6" class="edge">
+<title>core.compileIvyDeps&#45;&gt;core.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M1827.8689,-77.7862C1753.7094,-64.7312 1636.64,-44.1224 1561.1544,-30.834"/>
+<polygon fill="#000000" stroke="#000000" points="1561.7015,-27.3766 1551.2461,-29.0898 1560.4879,-34.2706 1561.7015,-27.3766"/>
+</g>
+<!-- core.scalaLibraryIvyDeps -->
+<g id="node25" class="node">
+<title>core.scalaLibraryIvyDeps</title>
+<ellipse fill="none" stroke="#000000" cx="2578.2502" cy="-90" rx="111.0741" ry="18"/>
+<text text-anchor="middle" x="2578.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalaLibraryIvyDeps</text>
+</g>
+<!-- core.scalaLibraryIvyDeps&#45;&gt;core.scalaVersion -->
+<g id="edge7" class="edge">
+<title>core.scalaLibraryIvyDeps&#45;&gt;core.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M2499.9556,-77.1805C2486.0903,-75.2177 2471.767,-73.387 2458.2502,-72 2135.3632,-38.8688 1749.7764,-25.0337 1578.221,-20.2062"/>
+<polygon fill="#000000" stroke="#000000" points="1578.0709,-16.7008 1567.9775,-19.9215 1577.8764,-23.6981 1578.0709,-16.7008"/>
+</g>
+<!-- core.transitiveIvyDeps -->
+<g id="node26" class="node">
+<title>core.transitiveIvyDeps</title>
+<ellipse fill="none" stroke="#000000" cx="2108.2502" cy="-90" rx="98.934" ry="18"/>
+<text text-anchor="middle" x="2108.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.transitiveIvyDeps</text>
+</g>
+<!-- core.transitiveIvyDeps&#45;&gt;core.ivyDeps -->
+<g id="edge8" class="edge">
+<title>core.transitiveIvyDeps&#45;&gt;core.ivyDeps</title>
+<path fill="none" stroke="#000000" d="M2039.3028,-77.0232C2026.3687,-75.0116 2012.9289,-73.2046 2000.2502,-72 1344.7853,-9.7241 1177.3332,-56.9572 519.2502,-36 383.0378,-31.6622 224.0495,-25.0499 134.0536,-21.1628"/>
+<polygon fill="#000000" stroke="#000000" points="134.1031,-17.6618 123.961,-20.7258 133.8002,-24.6552 134.1031,-17.6618"/>
+</g>
+<!-- core.compileClasspath -->
+<g id="node27" class="node">
+<title>core.compileClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2108.2502" cy="-162" rx="98.9533" ry="18"/>
+<text text-anchor="middle" x="2108.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.compileClasspath</text>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.platformSuffix -->
+<g id="edge9" class="edge">
+<title>core.compileClasspath&#45;&gt;core.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M2035.865,-149.6815C1958.0501,-136.4157 1839.4369,-116.1213 1794.2502,-108 1787.2509,-106.742 1779.9686,-105.4132 1772.6838,-104.0704"/>
+<polygon fill="#000000" stroke="#000000" points="1773.2448,-100.6149 1762.7747,-102.2361 1771.9705,-107.4979 1773.2448,-100.6149"/>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.transitiveLocalClasspath -->
+<g id="edge13" class="edge">
+<title>core.compileClasspath&#45;&gt;core.transitiveLocalClasspath</title>
+<path fill="none" stroke="#000000" d="M2178.7028,-149.313C2191.1829,-147.3358 2204.0776,-145.4659 2216.2502,-144 2429.5281,-118.3156 2484.582,-130.205 2698.2502,-108 2709.7337,-106.8066 2721.7479,-105.4136 2733.6725,-103.9406"/>
+<polygon fill="#000000" stroke="#000000" points="2734.1686,-107.4059 2743.6545,-102.687 2733.2963,-100.4604 2734.1686,-107.4059"/>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.resources -->
+<g id="edge14" class="edge">
+<title>core.compileClasspath&#45;&gt;core.resources</title>
+<path fill="none" stroke="#000000" d="M2037.8583,-149.3697C2025.675,-147.4096 2013.1136,-145.5308 2001.2502,-144 1824.6605,-121.2143 1778.9523,-129.897 1602.2502,-108 1586.8356,-106.0898 1570.3033,-103.686 1554.7436,-101.2626"/>
+<polygon fill="#000000" stroke="#000000" points="1555.1044,-97.7763 1544.6806,-99.6723 1554.0116,-104.6905 1555.1044,-97.7763"/>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.unmanagedClasspath -->
+<g id="edge15" class="edge">
+<title>core.compileClasspath&#45;&gt;core.unmanagedClasspath</title>
+<path fill="none" stroke="#000000" d="M2157.9398,-146.3771C2192.7168,-135.4428 2239.3877,-120.769 2276.3971,-109.1328"/>
+<polygon fill="#000000" stroke="#000000" points="2277.5821,-112.4293 2286.0719,-106.091 2275.4825,-105.7515 2277.5821,-112.4293"/>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.compileIvyDeps -->
+<g id="edge10" class="edge">
+<title>core.compileClasspath&#45;&gt;core.compileIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2061.6841,-146.1102C2029.6512,-135.1795 1986.9456,-120.607 1953.0843,-109.0524"/>
+<polygon fill="#000000" stroke="#000000" points="1953.9285,-105.6424 1943.334,-105.7253 1951.6678,-112.2673 1953.9285,-105.6424"/>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.scalaLibraryIvyDeps -->
+<g id="edge11" class="edge">
+<title>core.compileClasspath&#45;&gt;core.scalaLibraryIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2180.8395,-149.723C2192.6691,-147.7737 2204.7965,-145.8063 2216.2502,-144 2323.6619,-127.0611 2350.7043,-124.0652 2458.2502,-108 2467.451,-106.6256 2477.0484,-105.1897 2486.6316,-103.7545"/>
+<polygon fill="#000000" stroke="#000000" points="2487.225,-107.2048 2496.596,-102.2617 2486.1878,-100.282 2487.225,-107.2048"/>
+</g>
+<!-- core.compileClasspath&#45;&gt;core.transitiveIvyDeps -->
+<g id="edge12" class="edge">
+<title>core.compileClasspath&#45;&gt;core.transitiveIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2108.2502,-143.8314C2108.2502,-136.131 2108.2502,-126.9743 2108.2502,-118.4166"/>
+<polygon fill="#000000" stroke="#000000" points="2111.7503,-118.4132 2108.2502,-108.4133 2104.7503,-118.4133 2111.7503,-118.4132"/>
+</g>
+<!-- core.scalaCompilerClasspath -->
+<g id="node28" class="node">
+<title>core.scalaCompilerClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="1565.2502" cy="-162" rx="123.2883" ry="18"/>
+<text text-anchor="middle" x="1565.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalaCompilerClasspath</text>
+</g>
+<!-- core.scalaCompilerClasspath&#45;&gt;core.scalaVersion -->
+<g id="edge16" class="edge">
+<title>core.scalaCompilerClasspath&#45;&gt;core.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M1499.0612,-146.722C1462.7208,-136.8489 1422.9066,-123.0617 1412.2502,-108 1403.009,-94.9386 1404.9111,-86.2175 1412.2502,-72 1419.127,-58.678 1430.9767,-47.927 1443.3006,-39.6306"/>
+<polygon fill="#000000" stroke="#000000" points="1445.2334,-42.55 1451.853,-34.2776 1441.5195,-36.6164 1445.2334,-42.55"/>
+</g>
+<!-- core.scalaCompilerClasspath&#45;&gt;core.platformSuffix -->
+<g id="edge17" class="edge">
+<title>core.scalaCompilerClasspath&#45;&gt;core.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M1597.4458,-144.5708C1615.6305,-134.7264 1638.5281,-122.3308 1657.9027,-111.8422"/>
+<polygon fill="#000000" stroke="#000000" points="1659.6822,-114.8589 1666.81,-107.0202 1656.3497,-108.7031 1659.6822,-114.8589"/>
+</g>
+<!-- core.scalacPluginClasspath -->
+<g id="node29" class="node">
+<title>core.scalacPluginClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="1307.2502" cy="-162" rx="116.3475" ry="18"/>
+<text text-anchor="middle" x="1307.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.scalacPluginClasspath</text>
+</g>
+<!-- core.scalacPluginClasspath&#45;&gt;core.scalaVersion -->
+<g id="edge18" class="edge">
+<title>core.scalacPluginClasspath&#45;&gt;core.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M1324.1664,-143.981C1342.4727,-124.9737 1372.9844,-94.6914 1402.2502,-72 1417.0415,-60.5315 1434.355,-49.2882 1449.5549,-40.0556"/>
+<polygon fill="#000000" stroke="#000000" points="1451.4427,-43.0048 1458.2252,-34.8655 1447.8473,-36.9987 1451.4427,-43.0048"/>
+</g>
+<!-- core.scalacPluginClasspath&#45;&gt;core.platformSuffix -->
+<g id="edge19" class="edge">
+<title>core.scalacPluginClasspath&#45;&gt;core.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M1382.1763,-148.2029C1451.3936,-135.457 1553.6941,-116.619 1623.011,-103.8548"/>
+<polygon fill="#000000" stroke="#000000" points="1623.7901,-107.2702 1632.9909,-102.0171 1622.5224,-100.386 1623.7901,-107.2702"/>
+</g>
+<!-- core.scalacPluginClasspath&#45;&gt;core.scalacPluginIvyDeps -->
+<g id="edge20" class="edge">
+<title>core.scalacPluginClasspath&#45;&gt;core.scalacPluginIvyDeps</title>
+<path fill="none" stroke="#000000" d="M1284.5086,-144.2022C1272.8979,-135.1156 1258.6044,-123.9294 1246.0236,-114.0836"/>
+<polygon fill="#000000" stroke="#000000" points="1248.0812,-111.2494 1238.049,-107.8425 1243.767,-116.7619 1248.0812,-111.2494"/>
+</g>
+<!-- core.compile -->
+<g id="node30" class="node">
+<title>core.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1979.2502" cy="-234" rx="61.3551" ry="18"/>
+<text text-anchor="middle" x="1979.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.compile</text>
+</g>
+<!-- core.compile&#45;&gt;core.scalacOptions -->
+<g id="edge25" class="edge">
+<title>core.compile&#45;&gt;core.scalacOptions</title>
+<path fill="none" stroke="#000000" d="M1917.8435,-233.5013C1762.4523,-231.6189 1341.2351,-222.6503 993.2502,-180 985.4806,-179.0477 977.3874,-177.8364 969.3528,-176.4936"/>
+<polygon fill="#000000" stroke="#000000" points="969.6878,-172.9993 959.2356,-174.732 968.487,-179.8956 969.6878,-172.9993"/>
+</g>
+<!-- core.compile&#45;&gt;core.javacOptions -->
+<g id="edge27" class="edge">
+<title>core.compile&#45;&gt;core.javacOptions</title>
+<path fill="none" stroke="#000000" d="M2028.5594,-223.1429C2084.5324,-210.8186 2176.168,-190.642 2238.749,-176.8627"/>
+<polygon fill="#000000" stroke="#000000" points="2239.52,-180.2768 2248.5334,-174.7083 2238.0147,-173.4406 2239.52,-180.2768"/>
+</g>
+<!-- core.compile&#45;&gt;core.upstreamCompileOutput -->
+<g id="edge28" class="edge">
+<title>core.compile&#45;&gt;core.upstreamCompileOutput</title>
+<path fill="none" stroke="#000000" d="M2035.578,-226.7742C2115.7151,-216.4786 2267.2364,-196.9543 2396.2502,-180 2406.9297,-178.5966 2418.0833,-177.1226 2429.204,-175.6477"/>
+<polygon fill="#000000" stroke="#000000" points="2429.9408,-179.0807 2439.3932,-174.2949 2429.0195,-172.1416 2429.9408,-179.0807"/>
+</g>
+<!-- core.compile&#45;&gt;core.allSourceFiles -->
+<g id="edge21" class="edge">
+<title>core.compile&#45;&gt;core.allSourceFiles</title>
+<path fill="none" stroke="#000000" d="M1918.2675,-232.3547C1784.5076,-228.2019 1455.4795,-215.0135 1182.2502,-180 1174.3783,-178.9912 1166.174,-177.7412 1158.0283,-176.3733"/>
+<polygon fill="#000000" stroke="#000000" points="1158.5998,-172.9203 1148.1479,-174.6548 1157.4002,-179.8167 1158.5998,-172.9203"/>
+</g>
+<!-- core.compile&#45;&gt;core.scalaCompilerBridgeSources -->
+<g id="edge22" class="edge">
+<title>core.compile&#45;&gt;core.scalaCompilerBridgeSources</title>
+<path fill="none" stroke="#000000" d="M1950.399,-218.0209C1932.7052,-208.2212 1909.7714,-195.5194 1890.2158,-184.6886"/>
+<polygon fill="#000000" stroke="#000000" points="1891.6567,-181.4858 1881.2131,-179.7025 1888.2652,-187.6093 1891.6567,-181.4858"/>
+</g>
+<!-- core.compile&#45;&gt;core.compileClasspath -->
+<g id="edge23" class="edge">
+<title>core.compile&#45;&gt;core.compileClasspath</title>
+<path fill="none" stroke="#000000" d="M2007.8795,-218.0209C2025.7741,-208.0332 2049.0698,-195.0309 2068.7131,-184.0672"/>
+<polygon fill="#000000" stroke="#000000" points="2070.4226,-187.1214 2077.4488,-179.1915 2067.011,-181.009 2070.4226,-187.1214"/>
+</g>
+<!-- core.compile&#45;&gt;core.scalaCompilerClasspath -->
+<g id="edge24" class="edge">
+<title>core.compile&#45;&gt;core.scalaCompilerClasspath</title>
+<path fill="none" stroke="#000000" d="M1926.3963,-224.808C1857.899,-212.8955 1737.4504,-191.9479 1654.618,-177.5422"/>
+<polygon fill="#000000" stroke="#000000" points="1655.1608,-174.0842 1644.7089,-175.8189 1653.9613,-180.9806 1655.1608,-174.0842"/>
+</g>
+<!-- core.compile&#45;&gt;core.scalacPluginClasspath -->
+<g id="edge26" class="edge">
+<title>core.compile&#45;&gt;core.scalacPluginClasspath</title>
+<path fill="none" stroke="#000000" d="M1920.1769,-229.0024C1819.9147,-220.3312 1610.0894,-201.366 1433.2502,-180 1422.943,-178.7547 1412.175,-177.3601 1401.4625,-175.9131"/>
+<polygon fill="#000000" stroke="#000000" points="1401.6077,-172.4005 1391.2256,-174.5128 1400.659,-179.3359 1401.6077,-172.4005"/>
+</g>
+<!-- core.localClasspath -->
+<g id="node31" class="node">
+<title>core.localClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2382.2502" cy="-306" rx="86.2717" ry="18"/>
+<text text-anchor="middle" x="2382.2502" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.localClasspath</text>
+</g>
+<!-- core.localClasspath&#45;&gt;core.compile -->
+<g id="edge29" class="edge">
+<title>core.localClasspath&#45;&gt;core.compile</title>
+<path fill="none" stroke="#000000" d="M2316.6043,-294.2717C2240.6636,-280.7041 2116.5345,-258.5272 2041.8925,-245.1917"/>
+<polygon fill="#000000" stroke="#000000" points="2042.1585,-241.6839 2031.6988,-243.3705 2040.9273,-248.5747 2042.1585,-241.6839"/>
+</g>
+<!-- core.jar -->
+<g id="node32" class="node">
+<title>core.jar</title>
+<ellipse fill="none" stroke="#000000" cx="2425.2502" cy="-378" rx="40.0068" ry="18"/>
+<text text-anchor="middle" x="2425.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.jar</text>
+</g>
+<!-- core.jar&#45;&gt;core.mainClass -->
+<g id="edge31" class="edge">
+<title>core.jar&#45;&gt;core.mainClass</title>
+<path fill="none" stroke="#000000" d="M2441.5691,-361.268C2466.3051,-335.9658 2510.893,-290.6163 2515.2502,-288 2548.4664,-268.055 2589.6666,-254.9179 2623.9574,-246.6008"/>
+<polygon fill="#000000" stroke="#000000" points="2624.9555,-249.9618 2633.8959,-244.2767 2623.3616,-243.1457 2624.9555,-249.9618"/>
+</g>
+<!-- core.jar&#45;&gt;core.localClasspath -->
+<g id="edge30" class="edge">
+<title>core.jar&#45;&gt;core.localClasspath</title>
+<path fill="none" stroke="#000000" d="M2414.8411,-360.5708C2409.8824,-352.2679 2403.8399,-342.1502 2398.311,-332.8925"/>
+<polygon fill="#000000" stroke="#000000" points="2401.1448,-330.8114 2393.0125,-324.0206 2395.135,-334.4006 2401.1448,-330.8114"/>
+</g>
+<!-- core.pomSettings -->
+<g id="node33" class="node">
+<title>core.pomSettings</title>
+<ellipse fill="none" stroke="#000000" cx="364.2502" cy="-234" rx="78.2104" ry="18"/>
+<text text-anchor="middle" x="364.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.pomSettings</text>
+</g>
+<!-- core.pomSettings&#45;&gt;core.artifactName -->
+<g id="edge32" class="edge">
+<title>core.pomSettings&#45;&gt;core.artifactName</title>
+<path fill="none" stroke="#000000" d="M359.708,-215.8314C357.7618,-208.0463 355.4434,-198.7729 353.2839,-190.1347"/>
+<polygon fill="#000000" stroke="#000000" points="356.6744,-189.2658 350.8535,-180.4133 349.8834,-190.9636 356.6744,-189.2658"/>
+</g>
+<!-- core.artifactScalaVersion -->
+<g id="node34" class="node">
+<title>core.artifactScalaVersion</title>
+<ellipse fill="none" stroke="#000000" cx="977.2502" cy="-90" rx="108.7788" ry="18"/>
+<text text-anchor="middle" x="977.2502" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.artifactScalaVersion</text>
+</g>
+<!-- core.artifactScalaVersion&#45;&gt;core.scalaVersion -->
+<g id="edge34" class="edge">
+<title>core.artifactScalaVersion&#45;&gt;core.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M1056.5232,-77.6238C1069.1381,-75.7063 1082.0477,-73.7747 1094.2502,-72 1203.3428,-56.1335 1329.6239,-39.0522 1409.2129,-28.444"/>
+<polygon fill="#000000" stroke="#000000" points="1409.7132,-31.9083 1419.1637,-27.1189 1408.7892,-24.9696 1409.7132,-31.9083"/>
+</g>
+<!-- core.artifactScalaVersion&#45;&gt;core.crossFullScalaVersion -->
+<g id="edge33" class="edge">
+<title>core.artifactScalaVersion&#45;&gt;core.crossFullScalaVersion</title>
+<path fill="none" stroke="#000000" d="M981.7923,-71.8314C983.7386,-64.0463 986.057,-54.7729 988.2165,-46.1347"/>
+<polygon fill="#000000" stroke="#000000" points="991.6169,-46.9636 990.6469,-36.4133 984.8259,-45.2658 991.6169,-46.9636"/>
+</g>
+<!-- core.artifactSuffix -->
+<g id="node35" class="node">
+<title>core.artifactSuffix</title>
+<ellipse fill="none" stroke="#000000" cx="526.2502" cy="-162" rx="81.5934" ry="18"/>
+<text text-anchor="middle" x="526.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.artifactSuffix</text>
+</g>
+<!-- core.artifactSuffix&#45;&gt;core.artifactScalaVersion -->
+<g id="edge35" class="edge">
+<title>core.artifactSuffix&#45;&gt;core.artifactScalaVersion</title>
+<path fill="none" stroke="#000000" d="M585.7192,-149.6793C595.8889,-147.6948 606.3612,-145.7274 616.2502,-144 706.4275,-128.2474 809.7809,-113.0783 882.7269,-102.8501"/>
+<polygon fill="#000000" stroke="#000000" points="883.3944,-106.2909 892.8136,-101.44 882.4253,-99.3583 883.3944,-106.2909"/>
+</g>
+<!-- core.artifactId -->
+<g id="node36" class="node">
+<title>core.artifactId</title>
+<ellipse fill="none" stroke="#000000" cx="526.2502" cy="-234" rx="65.403" ry="18"/>
+<text text-anchor="middle" x="526.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.artifactId</text>
+</g>
+<!-- core.artifactId&#45;&gt;core.artifactName -->
+<g id="edge36" class="edge">
+<title>core.artifactId&#45;&gt;core.artifactName</title>
+<path fill="none" stroke="#000000" d="M488.9541,-219.0816C461.7289,-208.1915 424.569,-193.3275 394.9942,-181.4976"/>
+<polygon fill="#000000" stroke="#000000" points="396.2653,-178.2365 385.6807,-177.7722 393.6655,-184.7358 396.2653,-178.2365"/>
+</g>
+<!-- core.artifactId&#45;&gt;core.artifactSuffix -->
+<g id="edge37" class="edge">
+<title>core.artifactId&#45;&gt;core.artifactSuffix</title>
+<path fill="none" stroke="#000000" d="M526.2502,-215.8314C526.2502,-208.131 526.2502,-198.9743 526.2502,-190.4166"/>
+<polygon fill="#000000" stroke="#000000" points="529.7503,-190.4132 526.2502,-180.4133 522.7503,-190.4133 529.7503,-190.4132"/>
+</g>
+<!-- core.artifactMetadata -->
+<g id="node37" class="node">
+<title>core.artifactMetadata</title>
+<ellipse fill="none" stroke="#000000" cx="183.2502" cy="-306" rx="93.1701" ry="18"/>
+<text text-anchor="middle" x="183.2502" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.artifactMetadata</text>
+</g>
+<!-- core.artifactMetadata&#45;&gt;core.publishVersion -->
+<g id="edge40" class="edge">
+<title>core.artifactMetadata&#45;&gt;core.publishVersion</title>
+<path fill="none" stroke="#000000" d="M182.2408,-287.8314C181.813,-280.131 181.3043,-270.9743 180.8289,-262.4166"/>
+<polygon fill="#000000" stroke="#000000" points="184.3225,-262.2037 180.2731,-252.4133 177.3333,-262.592 184.3225,-262.2037"/>
+</g>
+<!-- core.artifactMetadata&#45;&gt;core.pomSettings -->
+<g id="edge38" class="edge">
+<title>core.artifactMetadata&#45;&gt;core.pomSettings</title>
+<path fill="none" stroke="#000000" d="M224.3219,-289.6621C251.4037,-278.8892 287.004,-264.7277 315.5182,-253.3851"/>
+<polygon fill="#000000" stroke="#000000" points="316.8958,-256.6039 324.894,-249.6555 314.3084,-250.0996 316.8958,-256.6039"/>
+</g>
+<!-- core.artifactMetadata&#45;&gt;core.artifactId -->
+<g id="edge39" class="edge">
+<title>core.artifactMetadata&#45;&gt;core.artifactId</title>
+<path fill="none" stroke="#000000" d="M249.7498,-293.3052C304.0664,-282.7669 382.7712,-267.1111 451.2502,-252 456.4806,-250.8458 461.9075,-249.6129 467.3419,-248.3539"/>
+<polygon fill="#000000" stroke="#000000" points="468.1523,-251.7589 477.091,-246.0712 466.5564,-244.9433 468.1523,-251.7589"/>
+</g>
+<!-- core.pom -->
+<g id="node38" class="node">
+<title>core.pom</title>
+<ellipse fill="none" stroke="#000000" cx="183.2502" cy="-378" rx="47.4743" ry="18"/>
+<text text-anchor="middle" x="183.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.pom</text>
+</g>
+<!-- core.pom&#45;&gt;core.ivyDeps -->
+<g id="edge41" class="edge">
+<title>core.pom&#45;&gt;core.ivyDeps</title>
+<path fill="none" stroke="#000000" d="M145.5957,-367.0357C123.5913,-358.7126 97.1114,-345.0396 81.2502,-324 56.6403,-291.3555 62.2502,-274.8816 62.2502,-234 62.2502,-234 62.2502,-234 62.2502,-162 62.2502,-121.876 62.2502,-75.4631 62.2502,-46.4177"/>
+<polygon fill="#000000" stroke="#000000" points="65.7503,-46.1853 62.2502,-36.1854 58.7503,-46.1854 65.7503,-46.1853"/>
+</g>
+<!-- core.pom&#45;&gt;core.artifactMetadata -->
+<g id="edge42" class="edge">
+<title>core.pom&#45;&gt;core.artifactMetadata</title>
+<path fill="none" stroke="#000000" d="M183.2502,-359.8314C183.2502,-352.131 183.2502,-342.9743 183.2502,-334.4166"/>
+<polygon fill="#000000" stroke="#000000" points="186.7503,-334.4132 183.2502,-324.4133 179.7503,-334.4133 186.7503,-334.4132"/>
+</g>
+<!-- core.ivy -->
+<g id="node39" class="node">
+<title>core.ivy</title>
+<ellipse fill="none" stroke="#000000" cx="49.2502" cy="-378" rx="42.3163" ry="18"/>
+<text text-anchor="middle" x="49.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.ivy</text>
+</g>
+<!-- core.ivy&#45;&gt;core.ivyDeps -->
+<g id="edge43" class="edge">
+<title>core.ivy&#45;&gt;core.ivyDeps</title>
+<path fill="none" stroke="#000000" d="M44.0702,-359.9889C36.7475,-332.8949 24.2502,-279.9269 24.2502,-234 24.2502,-234 24.2502,-234 24.2502,-162 24.2502,-120.3681 39.283,-74.14 50.4383,-45.567"/>
+<polygon fill="#000000" stroke="#000000" points="53.708,-46.817 54.1914,-36.2332 47.2133,-44.2055 53.708,-46.817"/>
+</g>
+<!-- core.ivy&#45;&gt;core.artifactMetadata -->
+<g id="edge44" class="edge">
+<title>core.ivy&#45;&gt;core.artifactMetadata</title>
+<path fill="none" stroke="#000000" d="M75.7243,-363.7751C94.8116,-353.5193 120.9277,-339.4867 142.6419,-327.8194"/>
+<polygon fill="#000000" stroke="#000000" points="144.4929,-330.7981 151.6452,-322.9818 141.1796,-324.6319 144.4929,-330.7981"/>
+</g>
+<!-- core.upstreamAssemblyClasspath -->
+<g id="node40" class="node">
+<title>core.upstreamAssemblyClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2816.2502" cy="-162" rx="141.7703" ry="18"/>
+<text text-anchor="middle" x="2816.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.upstreamAssemblyClasspath</text>
+</g>
+<!-- core.upstreamAssemblyClasspath&#45;&gt;core.platformSuffix -->
+<g id="edge45" class="edge">
+<title>core.upstreamAssemblyClasspath&#45;&gt;core.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M2717.5199,-149.0405C2700.4462,-147.1178 2682.8515,-145.3367 2666.2502,-144 2279.6158,-112.8689 2179.6487,-151.8552 1794.2502,-108 1786.2847,-107.0936 1777.9872,-105.9081 1769.7519,-104.5774"/>
+<polygon fill="#000000" stroke="#000000" points="1770.2072,-101.1049 1759.7641,-102.8914 1769.0419,-108.0072 1770.2072,-101.1049"/>
+</g>
+<!-- core.upstreamAssemblyClasspath&#45;&gt;core.transitiveLocalClasspath -->
+<g id="edge49" class="edge">
+<title>core.upstreamAssemblyClasspath&#45;&gt;core.transitiveLocalClasspath</title>
+<path fill="none" stroke="#000000" d="M2820.54,-143.8314C2822.3582,-136.131 2824.5201,-126.9743 2826.5407,-118.4166"/>
+<polygon fill="#000000" stroke="#000000" points="2830.0109,-118.95 2828.9026,-108.4133 2823.1983,-117.3414 2830.0109,-118.95"/>
+</g>
+<!-- core.upstreamAssemblyClasspath&#45;&gt;core.unmanagedClasspath -->
+<g id="edge50" class="edge">
+<title>core.upstreamAssemblyClasspath&#45;&gt;core.unmanagedClasspath</title>
+<path fill="none" stroke="#000000" d="M2724.7438,-148.2454C2639.8524,-135.4851 2514.1632,-116.5924 2429.147,-103.8133"/>
+<polygon fill="#000000" stroke="#000000" points="2429.6541,-100.3503 2419.2449,-102.3249 2428.6136,-107.2725 2429.6541,-100.3503"/>
+</g>
+<!-- core.upstreamAssemblyClasspath&#45;&gt;core.runIvyDeps -->
+<g id="edge46" class="edge">
+<title>core.upstreamAssemblyClasspath&#45;&gt;core.runIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2870.9865,-145.3008C2908.3602,-133.8986 2957.7552,-118.829 2995.5421,-107.3008"/>
+<polygon fill="#000000" stroke="#000000" points="2996.8339,-110.566 3005.3773,-104.3002 2994.7912,-103.8707 2996.8339,-110.566"/>
+</g>
+<!-- core.upstreamAssemblyClasspath&#45;&gt;core.scalaLibraryIvyDeps -->
+<g id="edge47" class="edge">
+<title>core.upstreamAssemblyClasspath&#45;&gt;core.scalaLibraryIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2761.3493,-145.3913C2725.3081,-134.4881 2678.0856,-120.2023 2640.6252,-108.8697"/>
+<polygon fill="#000000" stroke="#000000" points="2641.4165,-105.4525 2630.8314,-105.9069 2639.3895,-112.1527 2641.4165,-105.4525"/>
+</g>
+<!-- core.upstreamAssemblyClasspath&#45;&gt;core.transitiveIvyDeps -->
+<g id="edge48" class="edge">
+<title>core.upstreamAssemblyClasspath&#45;&gt;core.transitiveIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2715.4527,-149.349C2699.0201,-147.4464 2682.1702,-145.5914 2666.2502,-144 2466.6062,-124.0435 2415.3859,-132.5147 2216.2502,-108 2207.3138,-106.8999 2197.9869,-105.5906 2188.7201,-104.1873"/>
+<polygon fill="#000000" stroke="#000000" points="2189.128,-100.7088 2178.7094,-102.6331 2188.054,-107.6259 2189.128,-100.7088"/>
+</g>
+<!-- core.runClasspath -->
+<g id="node41" class="node">
+<title>core.runClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2286.2502" cy="-378" rx="80.4766" ry="18"/>
+<text text-anchor="middle" x="2286.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.runClasspath</text>
+</g>
+<!-- core.runClasspath&#45;&gt;core.localClasspath -->
+<g id="edge51" class="edge">
+<title>core.runClasspath&#45;&gt;core.localClasspath</title>
+<path fill="none" stroke="#000000" d="M2309.4891,-360.5708C2321.8966,-351.2652 2337.3437,-339.6799 2350.8092,-329.5807"/>
+<polygon fill="#000000" stroke="#000000" points="2352.9925,-332.3183 2358.8925,-323.5182 2348.7925,-326.7183 2352.9925,-332.3183"/>
+</g>
+<!-- core.runClasspath&#45;&gt;core.upstreamAssemblyClasspath -->
+<g id="edge52" class="edge">
+<title>core.runClasspath&#45;&gt;core.upstreamAssemblyClasspath</title>
+<path fill="none" stroke="#000000" d="M2280.5311,-359.9649C2275.4462,-340.0922 2271.0604,-308.2664 2287.2502,-288 2314.368,-254.054 2576.0125,-203.7773 2720.8797,-178.2079"/>
+<polygon fill="#000000" stroke="#000000" points="2721.8608,-181.5892 2731.1035,-176.4102 2720.6484,-174.695 2721.8608,-181.5892"/>
+</g>
+<!-- core.finalMainClassOpt -->
+<g id="node42" class="node">
+<title>core.finalMainClassOpt</title>
+<ellipse fill="none" stroke="#000000" cx="2628.2502" cy="-306" rx="103.6059" ry="18"/>
+<text text-anchor="middle" x="2628.2502" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.finalMainClassOpt</text>
+</g>
+<!-- core.finalMainClassOpt&#45;&gt;core.mainClass -->
+<g id="edge53" class="edge">
+<title>core.finalMainClassOpt&#45;&gt;core.mainClass</title>
+<path fill="none" stroke="#000000" d="M2644.0704,-288.2022C2651.8207,-279.4832 2661.2892,-268.8311 2669.7747,-259.2849"/>
+<polygon fill="#000000" stroke="#000000" points="2672.5842,-261.3924 2676.6119,-251.593 2667.3523,-256.7419 2672.5842,-261.3924"/>
+</g>
+<!-- core.finalMainClassOpt&#45;&gt;core.compile -->
+<g id="edge54" class="edge">
+<title>core.finalMainClassOpt&#45;&gt;core.compile</title>
+<path fill="none" stroke="#000000" d="M2543.2182,-295.7031C2521.6996,-293.1415 2498.6289,-290.4332 2477.2502,-288 2323.6419,-270.5169 2143.2244,-251.275 2047.3052,-241.1479"/>
+<polygon fill="#000000" stroke="#000000" points="2047.4741,-237.6463 2037.1621,-240.0777 2046.7396,-244.6077 2047.4741,-237.6463"/>
+</g>
+<!-- core.docJar -->
+<g id="node43" class="node">
+<title>core.docJar</title>
+<ellipse fill="none" stroke="#000000" cx="1103.2502" cy="-234" rx="55.0374" ry="18"/>
+<text text-anchor="middle" x="1103.2502" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.docJar</text>
+</g>
+<!-- core.docJar&#45;&gt;core.scalacOptions -->
+<g id="edge57" class="edge">
+<title>core.docJar&#45;&gt;core.scalacOptions</title>
+<path fill="none" stroke="#000000" d="M1065.3574,-220.6261C1033.6552,-209.4371 988.0586,-193.3441 952.6549,-180.8487"/>
+<polygon fill="#000000" stroke="#000000" points="953.5543,-177.4546 942.9595,-177.4268 951.2245,-184.0556 953.5543,-177.4546"/>
+</g>
+<!-- core.docJar&#45;&gt;core.allSources -->
+<g id="edge55" class="edge">
+<title>core.docJar&#45;&gt;core.allSources</title>
+<path fill="none" stroke="#000000" d="M1049.2697,-229.9938C974.3169,-223.4736 843.7004,-208.3498 806.2502,-180 786.3205,-164.9133 774.9004,-138.4005 768.7165,-118.0458"/>
+<polygon fill="#000000" stroke="#000000" points="772.0686,-117.0362 766.0148,-108.3412 765.3251,-118.9136 772.0686,-117.0362"/>
+</g>
+<!-- core.docJar&#45;&gt;core.compileClasspath -->
+<g id="edge59" class="edge">
+<title>core.docJar&#45;&gt;core.compileClasspath</title>
+<path fill="none" stroke="#000000" d="M1158.6079,-232.7233C1299.5927,-229.027 1683.5152,-216.1743 2001.2502,-180 2010.1844,-178.9828 2019.507,-177.7192 2028.7626,-176.3363"/>
+<polygon fill="#000000" stroke="#000000" points="2029.4082,-179.7782 2038.7579,-174.795 2028.3413,-172.86 2029.4082,-179.7782"/>
+</g>
+<!-- core.docJar&#45;&gt;core.scalaCompilerClasspath -->
+<g id="edge58" class="edge">
+<title>core.docJar&#45;&gt;core.scalaCompilerClasspath</title>
+<path fill="none" stroke="#000000" d="M1153.1312,-226.2263C1228.9619,-214.4086 1374.5761,-191.7154 1470.8279,-176.7152"/>
+<polygon fill="#000000" stroke="#000000" points="1471.5143,-180.1505 1480.856,-175.1523 1470.4363,-173.234 1471.5143,-180.1505"/>
+</g>
+<!-- core.docJar&#45;&gt;core.scalacPluginClasspath -->
+<g id="edge56" class="edge">
+<title>core.docJar&#45;&gt;core.scalacPluginClasspath</title>
+<path fill="none" stroke="#000000" d="M1141.1429,-220.6261C1171.8972,-209.7716 1215.7275,-194.3021 1250.6431,-181.979"/>
+<polygon fill="#000000" stroke="#000000" points="1251.9714,-185.2218 1260.2364,-178.5931 1249.6416,-178.6209 1251.9714,-185.2218"/>
+</g>
+<!-- core.ammoniteReplClasspath -->
+<g id="node44" class="node">
+<title>core.ammoniteReplClasspath</title>
+<ellipse fill="none" stroke="#000000" cx="2841.2502" cy="-378" rx="124.4552" ry="18"/>
+<text text-anchor="middle" x="2841.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.ammoniteReplClasspath</text>
+</g>
+<!-- core.ammoniteReplClasspath&#45;&gt;core.runIvyDeps -->
+<g id="edge60" class="edge">
+<title>core.ammoniteReplClasspath&#45;&gt;core.runIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2904.1054,-362.4013C2926.4973,-354.1556 2950.3311,-341.9024 2967.2502,-324 3023.1409,-264.8609 3042.7967,-166.1539 3049.2854,-118.0582"/>
+<polygon fill="#000000" stroke="#000000" points="3052.7684,-118.4114 3050.5417,-108.0533 3045.823,-117.5393 3052.7684,-118.4114"/>
+</g>
+<!-- core.ammoniteReplClasspath&#45;&gt;core.localClasspath -->
+<g id="edge61" class="edge">
+<title>core.ammoniteReplClasspath&#45;&gt;core.localClasspath</title>
+<path fill="none" stroke="#000000" d="M2756.7952,-364.7522C2672.5353,-351.5349 2544.0754,-331.3843 2461.6423,-318.4537"/>
+<polygon fill="#000000" stroke="#000000" points="2461.9961,-314.9664 2451.5744,-316.8744 2460.9112,-321.8819 2461.9961,-314.9664"/>
+</g>
+<!-- core.publishSelfDependency -->
+<g id="node45" class="node">
+<title>core.publishSelfDependency</title>
+<ellipse fill="none" stroke="#000000" cx="417.2502" cy="-306" rx="122.1369" ry="18"/>
+<text text-anchor="middle" x="417.2502" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.publishSelfDependency</text>
+</g>
+<!-- core.publishSelfDependency&#45;&gt;core.publishVersion -->
+<g id="edge64" class="edge">
+<title>core.publishSelfDependency&#45;&gt;core.publishVersion</title>
+<path fill="none" stroke="#000000" d="M363.5416,-289.752C326.5404,-278.5584 277.3416,-263.6747 239.085,-252.1013"/>
+<polygon fill="#000000" stroke="#000000" points="239.6928,-248.6286 229.1077,-249.0829 237.6658,-255.3287 239.6928,-248.6286"/>
+</g>
+<!-- core.publishSelfDependency&#45;&gt;core.pomSettings -->
+<g id="edge62" class="edge">
+<title>core.publishSelfDependency&#45;&gt;core.pomSettings</title>
+<path fill="none" stroke="#000000" d="M403.876,-287.8314C397.6777,-279.411 390.1977,-269.2495 383.414,-260.0338"/>
+<polygon fill="#000000" stroke="#000000" points="386.1833,-257.8919 377.4364,-251.9134 380.546,-262.0417 386.1833,-257.8919"/>
+</g>
+<!-- core.publishSelfDependency&#45;&gt;core.artifactId -->
+<g id="edge63" class="edge">
+<title>core.publishSelfDependency&#45;&gt;core.artifactId</title>
+<path fill="none" stroke="#000000" d="M443.9146,-288.3868C458.5918,-278.6918 476.9507,-266.5648 492.6058,-256.2238"/>
+<polygon fill="#000000" stroke="#000000" points="494.5695,-259.1214 500.9844,-250.6893 490.7113,-253.2806 494.5695,-259.1214"/>
+</g>
+<!-- core.sourceJar -->
+<g id="node46" class="node">
+<title>core.sourceJar</title>
+<ellipse fill="none" stroke="#000000" cx="692.2502" cy="-162" rx="66.5506" ry="18"/>
+<text text-anchor="middle" x="692.2502" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.sourceJar</text>
+</g>
+<!-- core.sourceJar&#45;&gt;core.resources -->
+<g id="edge66" class="edge">
+<title>core.sourceJar&#45;&gt;core.resources</title>
+<path fill="none" stroke="#000000" d="M748.0701,-152.1726C766.5426,-149.1917 787.2353,-146.1427 806.2502,-144 1040.8637,-117.5627 1101.1688,-129.8894 1336.2502,-108 1362.9953,-105.5097 1392.3177,-102.1796 1418.0123,-99.0612"/>
+<polygon fill="#000000" stroke="#000000" points="1418.5382,-102.5231 1428.0384,-97.833 1417.687,-95.575 1418.5382,-102.5231"/>
+</g>
+<!-- core.sourceJar&#45;&gt;core.allSources -->
+<g id="edge65" class="edge">
+<title>core.sourceJar&#45;&gt;core.allSources</title>
+<path fill="none" stroke="#000000" d="M709.1952,-144.5708C717.9009,-135.6164 728.6589,-124.551 738.207,-114.7302"/>
+<polygon fill="#000000" stroke="#000000" points="740.7572,-117.128 745.2186,-107.5182 735.7383,-112.2484 740.7572,-117.128"/>
+</g>
+<!-- core.publishArtifacts -->
+<g id="node47" class="node">
+<title>core.publishArtifacts</title>
+<ellipse fill="none" stroke="#000000" cx="1004.2502" cy="-450" rx="92.0709" ry="18"/>
+<text text-anchor="middle" x="1004.2502" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.publishArtifacts</text>
+</g>
+<!-- core.publishArtifacts&#45;&gt;core.jar -->
+<g id="edge67" class="edge">
+<title>core.publishArtifacts&#45;&gt;core.jar</title>
+<path fill="none" stroke="#000000" d="M1096.002,-448.0118C1382.7888,-441.5709 2250.6382,-420.2836 2375.2502,-396 2378.8583,-395.2969 2382.5544,-394.3766 2386.2238,-393.3238"/>
+<polygon fill="#000000" stroke="#000000" points="2387.3231,-396.647 2395.7956,-390.2855 2385.2053,-389.9751 2387.3231,-396.647"/>
+</g>
+<!-- core.publishArtifacts&#45;&gt;core.pom -->
+<g id="edge70" class="edge">
+<title>core.publishArtifacts&#45;&gt;core.pom</title>
+<path fill="none" stroke="#000000" d="M919.8644,-442.5995C752.2004,-427.8958 381.125,-395.3532 239.5941,-382.9412"/>
+<polygon fill="#000000" stroke="#000000" points="239.6742,-379.4349 229.4067,-382.0478 239.0626,-386.4082 239.6742,-379.4349"/>
+</g>
+<!-- core.publishArtifacts&#45;&gt;core.docJar -->
+<g id="edge69" class="edge">
+<title>core.publishArtifacts&#45;&gt;core.docJar</title>
+<path fill="none" stroke="#000000" d="M1012.5206,-431.9555C1029.9252,-393.9817 1070.414,-305.6426 1090.9029,-260.9396"/>
+<polygon fill="#000000" stroke="#000000" points="1094.0881,-262.3902 1095.0729,-251.8413 1087.7246,-259.4736 1094.0881,-262.3902"/>
+</g>
+<!-- core.publishArtifacts&#45;&gt;core.sourceJar -->
+<g id="edge68" class="edge">
+<title>core.publishArtifacts&#45;&gt;core.sourceJar</title>
+<path fill="none" stroke="#000000" d="M984.7332,-431.9843C930.8545,-382.2501 779.9892,-242.9899 718.6679,-186.3856"/>
+<polygon fill="#000000" stroke="#000000" points="720.6887,-183.4878 710.9667,-179.2767 715.9407,-188.6314 720.6887,-183.4878"/>
+</g>
+<!-- core.finalMainClass -->
+<g id="node48" class="node">
+<title>core.finalMainClass</title>
+<ellipse fill="none" stroke="#000000" cx="2609.2502" cy="-378" rx="89.139" ry="18"/>
+<text text-anchor="middle" x="2609.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.finalMainClass</text>
+</g>
+<!-- core.finalMainClass&#45;&gt;core.finalMainClassOpt -->
+<g id="edge71" class="edge">
+<title>core.finalMainClass&#45;&gt;core.finalMainClassOpt</title>
+<path fill="none" stroke="#000000" d="M2614.0447,-359.8314C2616.0991,-352.0463 2618.5462,-342.7729 2620.8257,-334.1347"/>
+<polygon fill="#000000" stroke="#000000" points="2624.2237,-334.9753 2623.3911,-324.4133 2617.4554,-333.1892 2624.2237,-334.9753"/>
+</g>
+<!-- core.prependShellScript -->
+<g id="node49" class="node">
+<title>core.prependShellScript</title>
+<ellipse fill="none" stroke="#000000" cx="3118.2502" cy="-306" rx="104.1721" ry="18"/>
+<text text-anchor="middle" x="3118.2502" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.prependShellScript</text>
+</g>
+<!-- core.prependShellScript&#45;&gt;core.mainClass -->
+<g id="edge72" class="edge">
+<title>core.prependShellScript&#45;&gt;core.mainClass</title>
+<path fill="none" stroke="#000000" d="M3043.5592,-293.3762C2963.8582,-279.9056 2838.6394,-258.7418 2761.2078,-245.6548"/>
+<polygon fill="#000000" stroke="#000000" points="2761.5191,-242.1579 2751.0757,-243.9423 2760.3525,-249.06 2761.5191,-242.1579"/>
+</g>
+<!-- core.prependShellScript&#45;&gt;core.forkArgs -->
+<g id="edge73" class="edge">
+<title>core.prependShellScript&#45;&gt;core.forkArgs</title>
+<path fill="none" stroke="#000000" d="M3134.5648,-288.2022C3142.6372,-279.396 3152.5172,-268.6179 3161.3345,-258.9989"/>
+<polygon fill="#000000" stroke="#000000" points="3163.946,-261.3296 3168.1232,-251.593 3158.7859,-256.5995 3163.946,-261.3296"/>
+</g>
+<!-- core.upstreamAssembly -->
+<g id="node50" class="node">
+<title>core.upstreamAssembly</title>
+<ellipse fill="none" stroke="#000000" cx="2854.2502" cy="-306" rx="104.1721" ry="18"/>
+<text text-anchor="middle" x="2854.2502" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.upstreamAssembly</text>
+</g>
+<!-- core.upstreamAssembly&#45;&gt;core.mainClass -->
+<g id="edge75" class="edge">
+<title>core.upstreamAssembly&#45;&gt;core.mainClass</title>
+<path fill="none" stroke="#000000" d="M2816.2684,-289.1192C2792.4686,-278.5415 2761.6886,-264.8615 2736.7473,-253.7765"/>
+<polygon fill="#000000" stroke="#000000" points="2738.0605,-250.5301 2727.5009,-249.667 2735.2175,-256.9268 2738.0605,-250.5301"/>
+</g>
+<!-- core.upstreamAssembly&#45;&gt;core.upstreamAssemblyClasspath -->
+<g id="edge74" class="edge">
+<title>core.upstreamAssembly&#45;&gt;core.upstreamAssemblyClasspath</title>
+<path fill="none" stroke="#000000" d="M2849.4375,-287.7623C2842.9275,-263.0928 2831.2548,-218.8598 2823.632,-189.9731"/>
+<polygon fill="#000000" stroke="#000000" points="2826.9596,-188.8656 2821.0238,-180.0896 2820.1913,-190.6517 2826.9596,-188.8656"/>
+</g>
+<!-- core.assembly -->
+<g id="node51" class="node">
+<title>core.assembly</title>
+<ellipse fill="none" stroke="#000000" cx="3049.2502" cy="-378" rx="66.0096" ry="18"/>
+<text text-anchor="middle" x="3049.2502" y="-373.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.assembly</text>
+</g>
+<!-- core.assembly&#45;&gt;core.localClasspath -->
+<g id="edge76" class="edge">
+<title>core.assembly&#45;&gt;core.localClasspath</title>
+<path fill="none" stroke="#000000" d="M3001.8653,-365.4375C2992.7515,-363.3599 2983.2439,-361.4229 2974.2502,-360 2772.1375,-328.024 2718.7196,-345.7304 2515.2502,-324 2498.4001,-322.2004 2480.39,-319.9706 2463.2388,-317.7003"/>
+<polygon fill="#000000" stroke="#000000" points="2463.6313,-314.2217 2453.2549,-316.3618 2462.7011,-321.1596 2463.6313,-314.2217"/>
+</g>
+<!-- core.assembly&#45;&gt;core.prependShellScript -->
+<g id="edge77" class="edge">
+<title>core.assembly&#45;&gt;core.prependShellScript</title>
+<path fill="none" stroke="#000000" d="M3065.9532,-360.5708C3074.3874,-351.7698 3084.7759,-340.9297 3094.0655,-331.2362"/>
+<polygon fill="#000000" stroke="#000000" points="3096.8296,-333.4105 3101.2217,-323.7689 3091.7756,-328.5671 3096.8296,-333.4105"/>
+</g>
+<!-- core.assembly&#45;&gt;core.upstreamAssembly -->
+<g id="edge78" class="edge">
+<title>core.assembly&#45;&gt;core.upstreamAssembly</title>
+<path fill="none" stroke="#000000" d="M3009.789,-363.4297C2980.5411,-352.6305 2940.3376,-337.7861 2908.132,-325.8948"/>
+<polygon fill="#000000" stroke="#000000" points="2909.0082,-322.4874 2898.4149,-322.307 2906.5836,-329.0541 2909.0082,-322.4874"/>
+</g>
+<!-- core.launcher -->
+<g id="node52" class="node">
+<title>core.launcher</title>
+<ellipse fill="none" stroke="#000000" cx="2609.2502" cy="-450" rx="63.1235" ry="18"/>
+<text text-anchor="middle" x="2609.2502" y="-445.8" font-family="Times,serif" font-size="14.00" fill="#000000">core.launcher</text>
+</g>
+<!-- core.launcher&#45;&gt;core.forkArgs -->
+<g id="edge81" class="edge">
+<title>core.launcher&#45;&gt;core.forkArgs</title>
+<path fill="none" stroke="#000000" d="M2654.7211,-437.4362C2663.4721,-435.3587 2672.6048,-433.4221 2681.2502,-432 2876.1687,-399.9374 2937.8037,-461.2605 3124.2502,-396 3178.3513,-377.0634 3204.3122,-374.5952 3231.2502,-324 3238.7696,-309.877 3236.8581,-302.985 3231.2502,-288 3227.1812,-277.1273 3219.8245,-266.9998 3212.1209,-258.5213"/>
+<polygon fill="#000000" stroke="#000000" points="3214.5111,-255.9588 3205.033,-251.2243 3209.49,-260.8361 3214.5111,-255.9588"/>
+</g>
+<!-- core.launcher&#45;&gt;core.runClasspath -->
+<g id="edge80" class="edge">
+<title>core.launcher&#45;&gt;core.runClasspath</title>
+<path fill="none" stroke="#000000" d="M2559.1358,-438.829C2503.8285,-426.5004 2414.5404,-406.5972 2353.2561,-392.9363"/>
+<polygon fill="#000000" stroke="#000000" points="2353.814,-389.4748 2343.2921,-390.7152 2352.291,-396.3072 2353.814,-389.4748"/>
+</g>
+<!-- core.launcher&#45;&gt;core.finalMainClass -->
+<g id="edge79" class="edge">
+<title>core.launcher&#45;&gt;core.finalMainClass</title>
+<path fill="none" stroke="#000000" d="M2609.2502,-431.8314C2609.2502,-424.131 2609.2502,-414.9743 2609.2502,-406.4166"/>
+<polygon fill="#000000" stroke="#000000" points="2612.7503,-406.4132 2609.2502,-396.4133 2605.7503,-406.4133 2612.7503,-406.4132"/>
+</g>
+</g>
+</svg>
diff --git a/VisualizePlan.svg b/VisualizePlan.svg
new file mode 100644
index 00000000..9f13384f
--- /dev/null
+++ b/VisualizePlan.svg
@@ -0,0 +1,355 @@
+<svg width="3473pt" height="332pt"
+ viewBox="0.00 0.00 3473.15 332.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 328)">
+<title>example1</title>
+<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-328 3469.1473,-328 3469.1473,4 -4,4"/>
+<!-- mill.scalalib.ZincWorkerModule.classpath -->
+<g id="node1" class="node">
+<title>mill.scalalib.ZincWorkerModule.classpath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="179.1736" cy="-162" rx="179.3473" ry="18"/>
+<text text-anchor="middle" x="179.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">mill.scalalib.ZincWorkerModule.classpath</text>
+</g>
+<!-- mill.scalalib.ZincWorkerModule.compilerInterfaceClasspath -->
+<g id="node2" class="node">
+<title>mill.scalalib.ZincWorkerModule.compilerInterfaceClasspath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="626.1736" cy="-162" rx="249.9102" ry="18"/>
+<text text-anchor="middle" x="626.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">mill.scalalib.ZincWorkerModule.compilerInterfaceClasspath</text>
+</g>
+<!-- mill.scalalib.ZincWorkerModule.worker -->
+<g id="node3" class="node">
+<title>mill.scalalib.ZincWorkerModule.worker</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="626.1736" cy="-234" rx="171.2452" ry="18"/>
+<text text-anchor="middle" x="626.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">mill.scalalib.ZincWorkerModule.worker</text>
+</g>
+<!-- mill.scalalib.ZincWorkerModule.worker&#45;&gt;mill.scalalib.ZincWorkerModule.classpath -->
+<g id="edge1" class="edge">
+<title>mill.scalalib.ZincWorkerModule.worker&#45;&gt;mill.scalalib.ZincWorkerModule.classpath</title>
+<path fill="none" stroke="#000000" d="M532.4677,-218.9064C459.9462,-207.2251 359.5232,-191.0496 284.2741,-178.9289"/>
+<polygon fill="#000000" stroke="#000000" points="284.7249,-175.4565 274.2956,-177.3217 283.6117,-182.3675 284.7249,-175.4565"/>
+</g>
+<!-- mill.scalalib.ZincWorkerModule.worker&#45;&gt;mill.scalalib.ZincWorkerModule.compilerInterfaceClasspath -->
+<g id="edge2" class="edge">
+<title>mill.scalalib.ZincWorkerModule.worker&#45;&gt;mill.scalalib.ZincWorkerModule.compilerInterfaceClasspath</title>
+<path fill="none" stroke="#000000" d="M626.1736,-215.8314C626.1736,-208.131 626.1736,-198.9743 626.1736,-190.4166"/>
+<polygon fill="#000000" stroke="#000000" points="629.6737,-190.4132 626.1736,-180.4133 622.6737,-190.4133 629.6737,-190.4132"/>
+</g>
+<!-- moduledefs.scalaVersion -->
+<g id="node4" class="node">
+<title>moduledefs.scalaVersion</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1907.1736" cy="-18" rx="108.2456" ry="18"/>
+<text text-anchor="middle" x="1907.1736" y="-13.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalaVersion</text>
+</g>
+<!-- moduledefs.sources -->
+<g id="node5" class="node">
+<title>moduledefs.sources</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="877.1736" cy="-90" rx="87.4212" ry="18"/>
+<text text-anchor="middle" x="877.1736" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.sources</text>
+</g>
+<!-- moduledefs.generatedSources -->
+<g id="node6" class="node">
+<title>moduledefs.generatedSources</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1109.1736" cy="-90" rx="126.7082" ry="18"/>
+<text text-anchor="middle" x="1109.1736" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.generatedSources</text>
+</g>
+<!-- moduledefs.allSources -->
+<g id="node7" class="node">
+<title>moduledefs.allSources</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="993.1736" cy="-162" rx="98.9552" ry="18"/>
+<text text-anchor="middle" x="993.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.allSources</text>
+</g>
+<!-- moduledefs.allSources&#45;&gt;moduledefs.sources -->
+<g id="edge3" class="edge">
+<title>moduledefs.allSources&#45;&gt;moduledefs.sources</title>
+<path fill="none" stroke="#000000" d="M965.0932,-144.5708C949.7048,-135.0194 930.447,-123.0662 913.8804,-112.7836"/>
+<polygon fill="#000000" stroke="#000000" points="915.3375,-109.5686 904.9953,-107.2687 911.646,-115.5161 915.3375,-109.5686"/>
+</g>
+<!-- moduledefs.allSources&#45;&gt;moduledefs.generatedSources -->
+<g id="edge4" class="edge">
+<title>moduledefs.allSources&#45;&gt;moduledefs.generatedSources</title>
+<path fill="none" stroke="#000000" d="M1021.2539,-144.5708C1036.416,-135.1599 1055.3346,-123.4173 1071.7341,-113.2383"/>
+<polygon fill="#000000" stroke="#000000" points="1073.8953,-116.0163 1080.5459,-107.7689 1070.2037,-110.0688 1073.8953,-116.0163"/>
+</g>
+<!-- moduledefs.allSourceFiles -->
+<g id="node8" class="node">
+<title>moduledefs.allSourceFiles</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="961.1736" cy="-234" rx="114" ry="18"/>
+<text text-anchor="middle" x="961.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.allSourceFiles</text>
+</g>
+<!-- moduledefs.allSourceFiles&#45;&gt;moduledefs.allSources -->
+<g id="edge5" class="edge">
+<title>moduledefs.allSourceFiles&#45;&gt;moduledefs.allSources</title>
+<path fill="none" stroke="#000000" d="M969.2485,-215.8314C972.7838,-207.8771 977.0096,-198.369 980.9192,-189.5723"/>
+<polygon fill="#000000" stroke="#000000" points="984.1268,-190.9729 984.9899,-180.4133 977.7301,-188.1299 984.1268,-190.9729"/>
+</g>
+<!-- moduledefs.scalaOrganization -->
+<g id="node9" class="node">
+<title>moduledefs.scalaOrganization</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1789.1736" cy="-90" rx="128.43" ry="18"/>
+<text text-anchor="middle" x="1789.1736" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalaOrganization</text>
+</g>
+<!-- moduledefs.scalaOrganization&#45;&gt;moduledefs.scalaVersion -->
+<g id="edge6" class="edge">
+<title>moduledefs.scalaOrganization&#45;&gt;moduledefs.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M1818.0396,-72.3868C1833.5833,-62.9026 1852.9412,-51.0909 1869.6419,-40.9007"/>
+<polygon fill="#000000" stroke="#000000" points="1871.8922,-43.6278 1878.6055,-35.4313 1868.2461,-37.6523 1871.8922,-43.6278"/>
+</g>
+<!-- moduledefs.platformSuffix -->
+<g id="node10" class="node">
+<title>moduledefs.platformSuffix</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1645.1736" cy="-162" rx="115.791" ry="18"/>
+<text text-anchor="middle" x="1645.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.platformSuffix</text>
+</g>
+<!-- moduledefs.scalaCompilerBridgeSources -->
+<g id="node11" class="node">
+<title>moduledefs.scalaCompilerBridgeSources</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1572.1736" cy="-234" rx="171.2665" ry="18"/>
+<text text-anchor="middle" x="1572.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalaCompilerBridgeSources</text>
+</g>
+<!-- moduledefs.scalaCompilerBridgeSources&#45;&gt;moduledefs.scalaOrganization -->
+<g id="edge7" class="edge">
+<title>moduledefs.scalaCompilerBridgeSources&#45;&gt;moduledefs.scalaOrganization</title>
+<path fill="none" stroke="#000000" d="M1549.1918,-216.0058C1527.7117,-197.0191 1501.5334,-166.7539 1520.1736,-144 1539.1527,-120.8323 1604.3924,-107.3955 1665.8661,-99.7198"/>
+<polygon fill="#000000" stroke="#000000" points="1666.5785,-103.1595 1676.0892,-98.4908 1665.7429,-96.2095 1666.5785,-103.1595"/>
+</g>
+<!-- moduledefs.scalaCompilerBridgeSources&#45;&gt;moduledefs.platformSuffix -->
+<g id="edge8" class="edge">
+<title>moduledefs.scalaCompilerBridgeSources&#45;&gt;moduledefs.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M1590.5946,-215.8314C1599.3932,-207.1533 1610.0669,-196.6257 1619.6335,-187.1902"/>
+<polygon fill="#000000" stroke="#000000" points="1622.3494,-189.4275 1627.0114,-179.9134 1617.4339,-184.4437 1622.3494,-189.4275"/>
+</g>
+<!-- moduledefs.transitiveLocalClasspath -->
+<g id="node12" class="node">
+<title>moduledefs.transitiveLocalClasspath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="3311.1736" cy="-162" rx="153.9476" ry="18"/>
+<text text-anchor="middle" x="3311.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.transitiveLocalClasspath</text>
+</g>
+<!-- moduledefs.resources -->
+<g id="node13" class="node">
+<title>moduledefs.resources</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1912.1736" cy="-162" rx="94.9242" ry="18"/>
+<text text-anchor="middle" x="1912.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.resources</text>
+</g>
+<!-- moduledefs.unmanagedClasspath -->
+<g id="node14" class="node">
+<title>moduledefs.unmanagedClasspath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2166.1736" cy="-162" rx="140.636" ry="18"/>
+<text text-anchor="middle" x="2166.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.unmanagedClasspath</text>
+</g>
+<!-- moduledefs.compileIvyDeps -->
+<g id="node15" class="node">
+<title>moduledefs.compileIvyDeps</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2447.1736" cy="-162" rx="122.1562" ry="18"/>
+<text text-anchor="middle" x="2447.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.compileIvyDeps</text>
+</g>
+<!-- moduledefs.scalaLibraryIvyDeps -->
+<g id="node16" class="node">
+<title>moduledefs.scalaLibraryIvyDeps</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2727.1736" cy="-162" rx="139.4477" ry="18"/>
+<text text-anchor="middle" x="2727.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalaLibraryIvyDeps</text>
+</g>
+<!-- moduledefs.scalaLibraryIvyDeps&#45;&gt;moduledefs.scalaOrganization -->
+<g id="edge9" class="edge">
+<title>moduledefs.scalaLibraryIvyDeps&#45;&gt;moduledefs.scalaOrganization</title>
+<path fill="none" stroke="#000000" d="M2627.8676,-149.2761C2611.289,-147.3607 2594.2566,-145.5208 2578.1736,-144 2346.7806,-122.1197 2076.4061,-105.5642 1919.7849,-96.8588"/>
+<polygon fill="#000000" stroke="#000000" points="1919.8129,-93.3551 1909.6346,-96.2968 1919.4258,-100.3444 1919.8129,-93.3551"/>
+</g>
+<!-- moduledefs.ivyDeps -->
+<g id="node17" class="node">
+<title>moduledefs.ivyDeps</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2519.1736" cy="-90" rx="90.8744" ry="18"/>
+<text text-anchor="middle" x="2519.1736" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.ivyDeps</text>
+</g>
+<!-- moduledefs.ivyDeps&#45;&gt;moduledefs.scalaVersion -->
+<g id="edge10" class="edge">
+<title>moduledefs.ivyDeps&#45;&gt;moduledefs.scalaVersion</title>
+<path fill="none" stroke="#000000" d="M2441.0417,-80.808C2330.0875,-67.7546 2126.9212,-43.8527 2005.748,-29.597"/>
+<polygon fill="#000000" stroke="#000000" points="2006.0673,-26.1105 1995.7268,-28.418 2005.2494,-33.0626 2006.0673,-26.1105"/>
+</g>
+<!-- moduledefs.transitiveIvyDeps -->
+<g id="node18" class="node">
+<title>moduledefs.transitiveIvyDeps</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="3012.1736" cy="-162" rx="127.3073" ry="18"/>
+<text text-anchor="middle" x="3012.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.transitiveIvyDeps</text>
+</g>
+<!-- moduledefs.transitiveIvyDeps&#45;&gt;moduledefs.ivyDeps -->
+<g id="edge11" class="edge">
+<title>moduledefs.transitiveIvyDeps&#45;&gt;moduledefs.ivyDeps</title>
+<path fill="none" stroke="#000000" d="M2923.4657,-149.0447C2832.3075,-135.7315 2691.4807,-115.1645 2602.384,-102.1524"/>
+<polygon fill="#000000" stroke="#000000" points="2602.7199,-98.6644 2592.3191,-100.6825 2601.7083,-105.591 2602.7199,-98.6644"/>
+</g>
+<!-- moduledefs.compileClasspath -->
+<g id="node19" class="node">
+<title>moduledefs.compileClasspath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2210.1736" cy="-234" rx="127.3266" ry="18"/>
+<text text-anchor="middle" x="2210.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.compileClasspath</text>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.platformSuffix -->
+<g id="edge12" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M2117.2736,-221.6242C2102.8463,-219.7254 2088.1099,-217.7994 2074.1736,-216 1961.9195,-201.5066 1833.0759,-185.3532 1746.1261,-174.5231"/>
+<polygon fill="#000000" stroke="#000000" points="1746.3545,-171.0246 1735.9987,-173.2621 1745.4896,-177.971 1746.3545,-171.0246"/>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.transitiveLocalClasspath -->
+<g id="edge16" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.transitiveLocalClasspath</title>
+<path fill="none" stroke="#000000" d="M2299.3012,-221.0789C2314.8982,-219.1395 2330.99,-217.343 2346.1736,-216 2701.5893,-184.5626 2792.439,-207.5964 3148.1736,-180 3162.843,-178.862 3178.2325,-177.4499 3193.4534,-175.9208"/>
+<polygon fill="#000000" stroke="#000000" points="3193.8304,-179.4006 3203.4221,-174.9007 3193.1177,-172.4369 3193.8304,-179.4006"/>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.resources -->
+<g id="edge17" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.resources</title>
+<path fill="none" stroke="#000000" d="M2145.8789,-218.4657C2097.2166,-206.7084 2030.5044,-190.59 1980.8102,-178.5833"/>
+<polygon fill="#000000" stroke="#000000" points="1981.3355,-175.1096 1970.7931,-176.1631 1979.6914,-181.9138 1981.3355,-175.1096"/>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.unmanagedClasspath -->
+<g id="edge18" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.unmanagedClasspath</title>
+<path fill="none" stroke="#000000" d="M2199.0705,-215.8314C2194.1061,-207.7079 2188.1514,-197.9637 2182.6808,-189.0118"/>
+<polygon fill="#000000" stroke="#000000" points="2185.6272,-187.121 2177.4261,-180.4133 2179.6542,-190.7712 2185.6272,-187.121"/>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.compileIvyDeps -->
+<g id="edge13" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.compileIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2263.9525,-217.6621C2299.5573,-206.8454 2346.407,-192.6126 2383.8187,-181.247"/>
+<polygon fill="#000000" stroke="#000000" points="2385.0566,-184.529 2393.6074,-178.2733 2383.0218,-177.8313 2385.0566,-184.529"/>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.scalaLibraryIvyDeps -->
+<g id="edge14" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.scalaLibraryIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2301.116,-221.3349C2390.853,-208.8377 2527.9263,-189.7482 2622.2309,-176.6148"/>
+<polygon fill="#000000" stroke="#000000" points="2622.9432,-180.0495 2632.3648,-175.2035 2621.9776,-173.1164 2622.9432,-180.0495"/>
+</g>
+<!-- moduledefs.compileClasspath&#45;&gt;moduledefs.transitiveIvyDeps -->
+<g id="edge15" class="edge">
+<title>moduledefs.compileClasspath&#45;&gt;moduledefs.transitiveIvyDeps</title>
+<path fill="none" stroke="#000000" d="M2300.4263,-221.236C2315.6763,-219.3142 2331.362,-217.4826 2346.1736,-216 2580.6566,-192.5281 2640.6794,-203.3605 2875.1736,-180 2886.9226,-178.8296 2899.2179,-177.4438 2911.4152,-175.9688"/>
+<polygon fill="#000000" stroke="#000000" points="2912.1266,-179.4078 2921.6238,-174.7116 2911.2709,-172.4602 2912.1266,-179.4078"/>
+</g>
+<!-- moduledefs.scalaCompilerClasspath -->
+<g id="node20" class="node">
+<title>moduledefs.scalaCompilerClasspath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1913.1736" cy="-234" rx="151.662" ry="18"/>
+<text text-anchor="middle" x="1913.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalaCompilerClasspath</text>
+</g>
+<!-- moduledefs.scalaCompilerClasspath&#45;&gt;moduledefs.scalaOrganization -->
+<g id="edge20" class="edge">
+<title>moduledefs.scalaCompilerClasspath&#45;&gt;moduledefs.scalaOrganization</title>
+<path fill="none" stroke="#000000" d="M1858.9423,-217.0532C1840.2937,-208.6864 1820.9213,-196.7021 1808.1736,-180 1794.7473,-162.4089 1790.2892,-137.491 1789.0244,-118.3329"/>
+<polygon fill="#000000" stroke="#000000" points="1792.5115,-117.9417 1788.609,-108.0917 1785.5172,-118.2254 1792.5115,-117.9417"/>
+</g>
+<!-- moduledefs.scalaCompilerClasspath&#45;&gt;moduledefs.platformSuffix -->
+<g id="edge19" class="edge">
+<title>moduledefs.scalaCompilerClasspath&#45;&gt;moduledefs.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M1851.689,-217.4817C1810.3987,-206.3888 1755.9632,-191.7644 1713.3467,-180.3152"/>
+<polygon fill="#000000" stroke="#000000" points="1714.1805,-176.9151 1703.6148,-177.7006 1712.3642,-183.6754 1714.1805,-176.9151"/>
+</g>
+<!-- moduledefs.scalacOptions -->
+<g id="node21" class="node">
+<title>moduledefs.scalacOptions</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2468.1736" cy="-234" rx="112.8404" ry="18"/>
+<text text-anchor="middle" x="2468.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalacOptions</text>
+</g>
+<!-- moduledefs.scalacPluginIvyDeps -->
+<g id="node22" class="node">
+<title>moduledefs.scalacPluginIvyDeps</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1333.1736" cy="-162" rx="140.0506" ry="18"/>
+<text text-anchor="middle" x="1333.1736" y="-157.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalacPluginIvyDeps</text>
+</g>
+<!-- moduledefs.scalacPluginClasspath -->
+<g id="node23" class="node">
+<title>moduledefs.scalacPluginClasspath</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="1238.1736" cy="-234" rx="144.7212" ry="18"/>
+<text text-anchor="middle" x="1238.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.scalacPluginClasspath</text>
+</g>
+<!-- moduledefs.scalacPluginClasspath&#45;&gt;moduledefs.scalaOrganization -->
+<g id="edge22" class="edge">
+<title>moduledefs.scalacPluginClasspath&#45;&gt;moduledefs.scalaOrganization</title>
+<path fill="none" stroke="#000000" d="M1214.4491,-216.0272C1191.8382,-196.7846 1164.0038,-166.0502 1184.1736,-144 1215.1031,-110.1869 1482.9602,-97.3958 1651.7374,-92.668"/>
+<polygon fill="#000000" stroke="#000000" points="1652.0537,-96.1607 1661.9541,-92.3882 1651.862,-89.1634 1652.0537,-96.1607"/>
+</g>
+<!-- moduledefs.scalacPluginClasspath&#45;&gt;moduledefs.platformSuffix -->
+<g id="edge21" class="edge">
+<title>moduledefs.scalacPluginClasspath&#45;&gt;moduledefs.platformSuffix</title>
+<path fill="none" stroke="#000000" d="M1321.5182,-219.256C1390.5664,-207.0411 1488.3678,-189.7396 1558.3574,-177.3581"/>
+<polygon fill="#000000" stroke="#000000" points="1559.2379,-180.7568 1568.4752,-175.5683 1558.0184,-173.8638 1559.2379,-180.7568"/>
+</g>
+<!-- moduledefs.scalacPluginClasspath&#45;&gt;moduledefs.scalacPluginIvyDeps -->
+<g id="edge23" class="edge">
+<title>moduledefs.scalacPluginClasspath&#45;&gt;moduledefs.scalacPluginIvyDeps</title>
+<path fill="none" stroke="#000000" d="M1261.6567,-216.2022C1273.6461,-207.1156 1288.4056,-195.9294 1301.3967,-186.0836"/>
+<polygon fill="#000000" stroke="#000000" points="1303.7757,-188.6722 1309.6313,-179.8425 1299.5475,-183.0934 1303.7757,-188.6722"/>
+</g>
+<!-- moduledefs.javacOptions -->
+<g id="node24" class="node">
+<title>moduledefs.javacOptions</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2708.1736" cy="-234" rx="109.4125" ry="18"/>
+<text text-anchor="middle" x="2708.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.javacOptions</text>
+</g>
+<!-- moduledefs.upstreamCompileOutput -->
+<g id="node25" class="node">
+<title>moduledefs.upstreamCompileOutput</title>
+<ellipse fill="none" stroke="#000000" stroke-dasharray="1,5" cx="2989.1736" cy="-234" rx="153.9765" ry="18"/>
+<text text-anchor="middle" x="2989.1736" y="-229.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.upstreamCompileOutput</text>
+</g>
+<!-- moduledefs.compile -->
+<g id="node26" class="node">
+<title>moduledefs.compile</title>
+<ellipse fill="none" stroke="#000000" cx="1913.1736" cy="-306" rx="89.7283" ry="18"/>
+<text text-anchor="middle" x="1913.1736" y="-301.8" font-family="Times,serif" font-size="14.00" fill="#000000">moduledefs.compile</text>
+</g>
+<!-- moduledefs.compile&#45;&gt;mill.scalalib.ZincWorkerModule.worker -->
+<g id="edge24" class="edge">
+<title>moduledefs.compile&#45;&gt;mill.scalalib.ZincWorkerModule.worker</title>
+<path fill="none" stroke="#000000" d="M1824.9751,-302.6013C1641.2815,-295.2954 1204.2998,-276.7314 838.1736,-252 814.9556,-250.4316 790.326,-248.5451 766.3857,-246.592"/>
+<polygon fill="#000000" stroke="#000000" points="766.4274,-243.0836 756.174,-245.7515 765.8532,-250.06 766.4274,-243.0836"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.allSourceFiles -->
+<g id="edge25" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.allSourceFiles</title>
+<path fill="none" stroke="#000000" d="M1824.9422,-302.5812C1673.232,-296.1824 1353.2871,-280.4098 1084.1736,-252 1073.657,-250.8898 1062.6601,-249.5451 1051.7519,-248.0964"/>
+<polygon fill="#000000" stroke="#000000" points="1052.1558,-244.6192 1041.7755,-246.7405 1051.213,-251.5555 1052.1558,-244.6192"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.scalaCompilerBridgeSources -->
+<g id="edge26" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.scalaCompilerBridgeSources</title>
+<path fill="none" stroke="#000000" d="M1851.0254,-292.8778C1797.0709,-281.4857 1718.3988,-264.8745 1658.3635,-252.1985"/>
+<polygon fill="#000000" stroke="#000000" points="1659.0251,-248.7611 1648.5177,-250.1196 1657.5789,-255.6101 1659.0251,-248.7611"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.compileClasspath -->
+<g id="edge27" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.compileClasspath</title>
+<path fill="none" stroke="#000000" d="M1970.4382,-292.1177C2017.5307,-280.7013 2084.6092,-264.4398 2135.8416,-252.0199"/>
+<polygon fill="#000000" stroke="#000000" points="2136.9723,-255.3472 2145.8662,-249.5897 2135.3231,-248.5443 2136.9723,-255.3472"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.scalaCompilerClasspath -->
+<g id="edge28" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.scalaCompilerClasspath</title>
+<path fill="none" stroke="#000000" d="M1913.1736,-287.8314C1913.1736,-280.131 1913.1736,-270.9743 1913.1736,-262.4166"/>
+<polygon fill="#000000" stroke="#000000" points="1916.6737,-262.4132 1913.1736,-252.4133 1909.6737,-262.4133 1916.6737,-262.4132"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.scalacOptions -->
+<g id="edge29" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.scalacOptions</title>
+<path fill="none" stroke="#000000" d="M1990.6775,-296.8652C2077.3697,-286.524 2221.9429,-268.9089 2346.1736,-252 2355.8791,-250.679 2366.012,-249.2553 2376.1097,-247.8077"/>
+<polygon fill="#000000" stroke="#000000" points="2376.7806,-251.2473 2386.1784,-246.3552 2375.781,-244.319 2376.7806,-251.2473"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.scalacPluginClasspath -->
+<g id="edge30" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.scalacPluginClasspath</title>
+<path fill="none" stroke="#000000" d="M1832.8112,-297.9998C1730.4438,-287.7333 1548.0931,-269.1917 1392.1736,-252 1379.4875,-250.6012 1366.2179,-249.1031 1353.0162,-247.5905"/>
+<polygon fill="#000000" stroke="#000000" points="1353.2791,-244.0978 1342.9447,-246.4323 1352.4794,-251.0519 1353.2791,-244.0978"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.javacOptions -->
+<g id="edge31" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.javacOptions</title>
+<path fill="none" stroke="#000000" d="M1999.6635,-301.095C2128.5703,-293.3335 2378.6208,-276.5404 2590.1736,-252 2599.9,-250.8717 2610.0558,-249.5467 2620.1512,-248.1361"/>
+<polygon fill="#000000" stroke="#000000" points="2620.803,-251.5786 2630.2083,-246.701 2619.8141,-244.6488 2620.803,-251.5786"/>
+</g>
+<!-- moduledefs.compile&#45;&gt;moduledefs.upstreamCompileOutput -->
+<g id="edge32" class="edge">
+<title>moduledefs.compile&#45;&gt;moduledefs.upstreamCompileOutput</title>
+<path fill="none" stroke="#000000" d="M2001.0969,-302.2904C2164.0181,-295.0851 2523.7813,-277.6224 2826.1736,-252 2840.4644,-250.7891 2855.4427,-249.3578 2870.2843,-247.8397"/>
+<polygon fill="#000000" stroke="#000000" points="2870.9422,-251.2903 2880.5274,-246.7764 2870.2195,-244.3277 2870.9422,-251.2903"/>
+</g>
+</g>
+</svg>
diff --git a/example-1.zip b/example-1.zip
new file mode 100644
index 00000000..4048adb7
--- /dev/null
+++ b/example-1.zip
Binary files differ
diff --git a/example-2.zip b/example-2.zip
new file mode 100644
index 00000000..7a640469
--- /dev/null
+++ b/example-2.zip
Binary files differ
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 00000000..82430a78
--- /dev/null
+++ b/favicon.ico
Binary files differ
diff --git a/index.html b/index.html
new file mode 100644
index 00000000..84e98fad
--- /dev/null
+++ b/index.html
@@ -0,0 +1,628 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Intro to Mill</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href="" class=" Styles-subtleLink NarrowStyles-flexFont"><img src="logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="page/thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#installation">Installation</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#os-x">OS X</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#arch-linux">Arch Linux</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#freebsd">FreeBSD</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#windows">Windows</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#docker">Docker</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#manual">Manual</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#bootstrap-scripts-linuxos-x-only">Bootstrap Scripts (Linux/OS-X Only)</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#getting-started">Getting Started</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#output">Output</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#multiple-modules">Multiple Modules</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#java-example">Java Example</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scala-example">Scala Example</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#watch-and-re-evaluate">Watch and Re-evaluate</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#command-line-tools">Command-line Tools</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#all">all</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#resolve">resolve</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#inspect">inspect</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#show">show</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#path">path</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#plan">plan</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#visualize">visualize</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#visualizeplan">visualizePlan</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#clean">clean</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#search-for-dependency-updates">Search for dependency updates</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#intellij-support">IntelliJ Support</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#the-build-repl">The Build Repl</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#deploying-your-code">Deploying your code</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#structure-of-the-out-folder">Structure of the out/ folder</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#overriding-mill-versions">Overriding Mill Versions</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#development-releases">Development Releases</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Intro to Mill</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><div></div><a href="page/configuring-mill.html">Configuring Mill <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p><a href="https://github.com/lihaoyi/mill">Mill</a> is your shiny new Java/Scala build tool! <a href="http://www.lihaoyi.com/post/SowhatswrongwithSBT.html">Scared of SBT</a>? Melancholy over Maven? Grumbling about Gradle? Baffled by Bazel? Give Mill a try!</p>
+<p>Mill aims for simplicity by re-using concepts you are already <a href="http://www.lihaoyi.com/post/BuildToolsasPureFunctionalPrograms.html">familiar with</a>, borrowing ideas from modern tools like <a href="https://bazel.build/">Bazel</a>, to let you build your projects in a way that's simple, fast, and predictable.</p>
+<p>Mill has built in support for the <a href="https://www.scala-lang.org/">Scala</a> programming language, and can serve as a replacement for <a href="http://www.scala-sbt.org/">SBT</a>, but can also be <a href="http://www.lihaoyi.com/mill/page/extending-mill.html">extended</a> to support any other language or platform via modules (written in Java or Scala) or through external subprocesses.</p><h2 id="installation" class="Styles-hoverBox">Installation<a href="#installation" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2><h3 id="os-x" class="Styles-hoverBox">OS X<a href="#os-x" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Installation via <a href="https://github.com/Homebrew/homebrew-core/blob/master/Formula/mill.rb">homebrew</a>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="sh">brew install mill
+</code></pre><h3 id="arch-linux" class="Styles-hoverBox">Arch Linux<a href="#arch-linux" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Arch Linux has an <a href="https://aur.archlinux.org/packages/mill/">AUR package for mill</a>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">pacaur -S mill
+</code></pre><h3 id="freebsd" class="Styles-hoverBox">FreeBSD<a href="#freebsd" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Installation via <a href="http://man.freebsd.org/pkg/8">pkg(8)</a>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="sh">pkg install mill
+</code></pre><h3 id="windows" class="Styles-hoverBox">Windows<a href="#windows" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>To get started, download Mill from: <a href="https://github.com/lihaoyi/mill/releases/download/0.5.1/0.5.1-assembly">https://github.com/lihaoyi/mill/releases/download/0.5.1/0.5.1-assembly</a>, and save it as <code>mill.bat</code>.</p>
+<p>If you're using <a href="https://scoop.sh">Scoop</a> you can install Mill via</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">scoop install mill
+</code></pre>
+<p>Mill also works on a sh environment on Windows (e.g., <a href="https://www.msys2.org">MSYS2</a>, <a href="https://www.cygwin.com">Cygwin</a>, <a href="https://gitforwindows.org">Git-Bash</a>, <a href="https://docs.microsoft.com/en-us/windows/wsl">WSL</a>; to get started, follow the instructions in the <a href="#manual">manual</a> section below. Note that:</p>
+<ul>
+ <li>
+ <p>In some environments (such as WSL), mill might have to be run using interactive mode (<code>-i</code>)</p></li>
+ <li>
+ <p>On Cygwin, run the following after downloading mill:</p></li>
+</ul>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">sed -i &#39;0,/-cp &quot;\$0&quot;/{s/-cp &quot;\$0&quot;/-cp `cygpath -w &quot;\$0&quot;`/}; 0,/-cp &quot;\$0&quot;/{s/-cp &quot;\$0&quot;/-cp `cygpath -w &quot;\$0&quot;`/}&#39; /usr/local/bin/mill
+</code></pre><h3 id="docker" class="Styles-hoverBox">Docker<a href="#docker" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>You can download and run a <a href="https://hub.docker.com/r/nightscape/scala-mill/">Docker image containing OpenJDK, Scala and Mill</a> using</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">docker pull nightscape/scala-mill
+docker run -it nightscape/scala-mill
+</code></pre><h3 id="manual" class="Styles-hoverBox">Manual<a href="#manual" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>To get started, download Mill and install it into your system via the following <code>curl</code>/<code>chmod</code> command:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">sudo curl -L https://github.com/lihaoyi/mill/releases/download/0.5.1/0.5.1 &gt; /usr/local/bin/mill &amp;&amp; sudo chmod +x /usr/local/bin/mill
+</code></pre><h3 id="bootstrap-scripts-linuxos-x-only" class="Styles-hoverBox">Bootstrap Scripts (Linux/OS-X Only)<a href="#bootstrap-scripts-linuxos-x-only" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>If you are using Mill in a codebase, you can commit the bootstrap launcher as a <code>./mill</code> script in the project folder:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">curl -L https://github.com/lihaoyi/mill/releases/download/0.5.1/0.5.1 &gt; mill &amp;&amp; chmod +x mill
+</code></pre>
+<p>Now, anyone who wants to work with the project can simply use the <code>./mill</code> script directly:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">./mill version
+./mill __.compile
+</code></pre>
+<p>The <code>mill</code> command will automatically use the version specified by the bootstrap script, even if you installed it via other means. The <code>./mill</code> file has a version number embedded within it, which you can update simply by editing the script. Note this only works for versions 0.5.0 and above.</p>
+<p>Bootstrap scripts are also useful for running Mill in CI, ensuring that your Jenkins/Travis/etc. box has the correct version of Mill present to build/compile/test your code.</p><h2 id="getting-started" class="Styles-hoverBox">Getting Started<a href="#getting-started" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The simplest Mill build for a Java project looks as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends JavaModule {
+
+}
+</code></pre>
+<p>The simplest Mill build for a Scala project looks as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+</code></pre>
+<p>Both of these would build a project laid out as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">build.sc
+foo/
+ src/
+ FileA.java
+ FileB.scala
+ resources/
+ ...
+out/
+ foo/
+ ...
+</code></pre>
+<p>You can download an example project with this layout here:</p>
+<ul>
+ <li><a href="example-1.zip">Example 1</a></li>
+</ul>
+<p>The source code for this module would live in the <code>foo/src/</code> folder, matching the name you assigned to the module. Output for this module (compiled files, resolved dependency lists, ...) would live in <code>out/foo/</code>.</p>
+<p>This can be run from the Bash shell via:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill foo.compile # compile sources into classfiles
+
+$ mill foo.run # run the main method, if any
+
+$ mill foo.runBackground # run the main method in the background
+
+$ mill foo.launcher # prepares a foo/launcher/dest/run you can run later
+
+$ mill foo.jar # bundle the classfiles into a jar
+
+$ mill foo.assembly # bundle classfiles and all dependencies into a jar
+
+$ mill -i foo.console # start a Scala console within your project (in interactive mode: &quot;-i&quot;)
+
+$ mill -i foo.repl # start an Ammonite REPL within your project (in interactive mode: &quot;-i&quot;)
+</code></pre>
+<p>You can run <code>mill resolve __</code> to see a full list of the different tasks that are available, <code>mill resolve foo._</code> to see the tasks within <code>foo</code>, <code>mill inspect
+foo.compile</code> to inspect a task's doc-comment documentation or what it depends on, or <code>mill show foo.scalaVersion</code> to show the output of any task.</p>
+<p>The most common <strong>tasks</strong> that Mill can run are cached <strong>targets</strong>, such as <code>compile</code>, and un-cached <strong>commands</strong> such as <code>foo.run</code>. Targets do not re-evaluate unless one of their inputs changes, where-as commands re-run every time.</p><h2 id="output" class="Styles-hoverBox">Output<a href="#output" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill puts all its output in the top-level <code>out/</code> folder. The above commands would end up in:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">out/
+ foo/
+ compile/
+ run/
+ jar/
+ assembly/
+</code></pre>
+<p>Within the output folder for each task, there's a <code>meta.json</code> file containing the metadata returned by that task, and a <code>dest/</code> folder containing any files that the task generates. For example, <code>out/foo/compile/dest/</code> contains the compiled classfiles, while <code>out/foo/assembly/dest/</code> contains the self-contained assembly with the project's classfiles jar-ed up with all its dependencies.</p>
+<p>Given a task <code>foo.bar</code>, all its output and results can be found be within its respective <code>out/foo/bar/</code> folder.</p><h2 id="multiple-modules" class="Styles-hoverBox">Multiple Modules<a href="#multiple-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2><h3 id="java-example" class="Styles-hoverBox">Java Example<a href="#java-example" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends JavaModule
+object bar extends JavaModule {
+ def moduleDeps = Seq(foo)
+}
+</code></pre><h3 id="scala-example" class="Styles-hoverBox">Scala Example<a href="#scala-example" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+object bar extends ScalaModule {
+ def moduleDeps = Seq(foo)
+ def scalaVersion = &quot;2.12.4&quot;
+}
+</code></pre>
+<p>You can define multiple modules the same way you define a single module, using <code>def moduleDeps</code> to define the relationship between them. The above builds expects the following project layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">build.sc
+foo/
+ src/
+ Main.scala
+ resources/
+ ...
+bar/
+ src/
+ Main2.scala
+ resources/
+ ...
+out/
+ foo/
+ ...
+ bar/
+ ...
+</code></pre>
+<p>And can be built/run using:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill foo.compile
+$ mill bar.compile
+
+$ mill foo.run
+$ mill bar.run
+
+$ mill foo.jar
+$ mill bar.jar
+
+$ mill foo.assembly
+$ mill bar.assembly
+</code></pre>
+<p>Mill's evaluator will ensure that the modules are compiled in the right order, and re-compiled as necessary when source code in each module changes.</p>
+<p>Modules can also be nested:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ object bar extends ScalaModule {
+ def moduleDeps = Seq(foo)
+ def scalaVersion = &quot;2.12.4&quot;
+ }
+}
+</code></pre>
+<p>Which would result in a similarly nested project layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">build.sc
+foo/
+ src/
+ Main.scala
+ resources/
+ ...
+ bar/
+ src/
+ Main2.scala
+ resources/
+ ...
+out/
+ foo/
+ ...
+ bar/
+ ...
+</code></pre>
+<p>Where the nested modules can be run via:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill foo.compile
+$ mill foo.bar.compile
+
+$ mill foo.run
+$ mill foo.bar.run
+
+$ mill foo.jar
+$ mill foo.bar.jar
+
+$ mill foo.assembly
+$ mill foo.bar.assembly
+</code></pre><h2 id="watch-and-re-evaluate" class="Styles-hoverBox">Watch and Re-evaluate<a href="#watch-and-re-evaluate" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>You can use the <code>--watch</code> flag to make Mill watch a task's inputs, re-evaluating the task as necessary when the inputs change:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill --watch foo.compile
+$ mill --watch foo.run
+$ mill -w foo.compile
+$ mill -w foo.run
+</code></pre>
+<p>Mill's <code>--watch</code> flag watches both the files you are building using Mill, as well as Mill's own <code>build.sc</code> file and anything it imports, so any changes to your <code>build.sc</code> will automatically get picked up.</p>
+<p>For long-running processes like web-servers, you can use <code>.runBackground</code> to make sure they re-compile and re-start when code changes, forcefully terminating the previous process even though it may be still alive:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill -w foo.compile
+$ mill -w foo.runBackground
+</code></pre><h2 id="command-line-tools" class="Styles-hoverBox">Command-line Tools<a href="#command-line-tools" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill comes built in with a small number of useful command-line utilities:</p><h3 id="all" class="Styles-hoverBox">all<a href="#all" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill all foo.{compile,run}
+mill all &quot;foo.{compile,run}&quot;
+mill all foo.compile foo.run
+mill all _.compile # run compile for every top-level module
+mill all __.compile # run compile for every module
+</code></pre>
+<p><code>all</code> runs multiple tasks in a single command</p><h3 id="resolve" class="Styles-hoverBox">resolve<a href="#resolve" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill resolve _
+main
+moduledefs
+core
+scalaworker
+scalalib
+scalajslib
+integration
+testRepos
+...
+
+$ mill resolve _.compile
+
+main.compile
+moduledefs.compile
+core.compile
+scalalib.worker.compile
+scalalib.compile
+scalajslib.compile
+integration.compile
+
+$ mill resolve core._
+
+core.test
+core.compile
+core.publishVersion
+core.runClasspath
+core.testArgs
+core.sources
+...
+</code></pre>
+<p><code>resolve</code> lists the tasks that match a particular query, without running them. This is useful for "dry running" an <code>mill all</code> command to see what would be run before you run them, or to explore what modules or tasks are available from the command line using <code>resolve _</code>, <code>resolve foo._</code>, etc.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill resolve foo.{compile,run}
+mill resolve &quot;foo.{compile,run}&quot;
+mill resolve foo.compile foo.run
+mill resolve _.compile # list the compile tasks for every top-level module
+mill resolve __.compile # list the compile tasks for every module
+mill resolve _ # list every top level module or task
+mill resolve foo._ # list every task directly within the foo module
+mill resolve __ # list every module or task recursively
+mill resolve foo.__ # list every task recursively within the foo module
+</code></pre><h3 id="inspect" class="Styles-hoverBox">inspect<a href="#inspect" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill inspect core.run
+
+core.run(ScalaModule.scala:211)
+Inputs:
+ core.mainClass
+ core.runClasspath
+ core.forkArgs
+ core.forkEnv
+</code></pre>
+<p><code>inspect</code> is a more verbose version of <a href="#resolve">resolve</a>. In addition to printing out the name of one-or-more tasks, it also displays its source location and a list of input tasks. This is very useful for debugging and interactively exploring the structure of your build from the command line.</p>
+<p><code>inspect</code> also works with the same <code>_</code>/<code>__</code> wildcard/query syntaxes that <a href="#all">all</a>/<a href="#resolve">resolve</a> do:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill inspect foo.compile
+mill inspect foo.{compile,run}
+mill inspect &quot;foo.{compile,run}&quot;
+mill inspect foo.compile foo.run
+mill inspect _.compile
+mill inspect __.compile
+mill inspect _
+mill inspect foo._
+mill inspect __
+mill inspect foo._
+</code></pre><h3 id="show" class="Styles-hoverBox">show<a href="#show" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill show core.scalaVersion
+&quot;2.12.4&quot;
+</code></pre>
+<p>By default, Mill does not print out the metadata from evaluating a task. Most people would not be interested in e.g. viewing the metadata related to incremental compilation: they just want to compile their code! However, if you want to inspect the build to debug problems, you can make Mill show you the metadata output for a task using the <code>show</code> command:</p>
+<p>All tasks return values that can be <code>show</code>n, not just configuration values. e.g. <code>compile</code> returns that path to the <code>classes</code> and <code>analysisFile</code> that are produced by the compilation:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill show foo.compile
+{
+ &quot;analysisFile&quot;: &quot;/Users/lihaoyi/Dropbox/Github/test/out/foo/compile/dest/zinc&quot;,
+ &quot;classes&quot;: {
+ &quot;path&quot;: &quot;/Users/lihaoyi/Dropbox/Github/test/out/foo/compile/dest/classes&quot;
+ }
+}
+</code></pre>
+<p><code>show</code> is generally useful as a debugging tool, to see what is going on in your build:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill show foo.sources
+[
+ &quot;/Users/lihaoyi/Dropbox/Github/test/foo/src&quot;
+]
+
+$ mill show foo.compileDepClasspath
+[
+ &quot;.../org/scala-lang/scala-compiler/2.12.4/scala-compiler-2.12.4.jar&quot;,
+ &quot;.../org/scala-lang/scala-library/2.12.4/scala-library-2.12.4.jar&quot;,
+ &quot;.../org/scala-lang/scala-reflect/2.12.4/scala-reflect-2.12.4.jar&quot;,
+ &quot;.../org/scala-lang/modules/scala-xml_2.12/1.0.6/scala-xml_2.12-1.0.6.jar&quot;
+]
+</code></pre>
+<p><code>show</code> is also useful for interacting with Mill from external tools, since the JSON it outputs is structured and easily parsed &amp; manipulated.</p><h3 id="path" class="Styles-hoverBox">path<a href="#path" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill path core.assembly core.sources
+core.sources
+core.allSources
+core.allSourceFiles
+core.compile
+core.localClasspath
+core.assembly
+</code></pre>
+<p><code>mill path</code> prints out a dependency chain between the first task and the second. It is very useful for exploring the build graph and trying to figure out how data gets from one task to another. If there are multiple possible dependency chains, one of them is picked arbitrarily.</p><h3 id="plan" class="Styles-hoverBox">plan<a href="#plan" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill plan moduledefs.compileClasspath
+moduledefs.transitiveLocalClasspath
+moduledefs.resources
+moduledefs.unmanagedClasspath
+moduledefs.scalaVersion
+moduledefs.platformSuffix
+moduledefs.compileIvyDeps
+moduledefs.scalaLibraryIvyDeps
+moduledefs.ivyDeps
+moduledefs.transitiveIvyDeps
+moduledefs.compileClasspath
+</code></pre>
+<p><code>mill plan foo</code> prints out what tasks would be evaluated, in what order, if you ran <code>mill foo</code>, but without actually running them. This is a useful tool for debugging your build: e.g. if you suspect a task <code>foo</code> is running things that it shouldn't be running, a quick <code>mill plan</code> will list out all the upstream tasks that <code>foo</code> needs to run, and you can then follow up with <code>mill path</code> on any individual upstream task to see exactly how <code>foo</code> depends on it.</p><h3 id="visualize" class="Styles-hoverBox">visualize<a href="#visualize" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill show visualize core._
+[
+ &quot;.../out/visualize/dest/out.txt&quot;,
+ &quot;.../out/visualize/dest/out.dot&quot;,
+ &quot;.../out/visualize/dest/out.json&quot;,
+ &quot;.../out/visualize/dest/out.png&quot;,
+ &quot;.../out/visualize/dest/out.svg&quot;
+]
+</code></pre>
+<p><code>mill show visualize</code> takes a subset of the Mill build graph (e.g. <code>core._</code> is every task directly under the <code>core</code> module) and draws out their relationships in <code>.svg</code> and <code>.png</code> form for you to inspect. It also generates <code>.txt</code>, <code>.dot</code> and <code>.json</code> for easy processing by downstream tools.</p>
+<p>The above command generates the following diagram:</p>
+<p><div style="text-align: center"><img src="VisualizeCore.svg" alt="VisualizeCore.svg" style="max-width: 100%; max-height: 500px" /></div></p>
+<p>Another use case is to view the relationships between modules:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill show visualize __.compile
+</code></pre>
+<p>This command diagrams the relationships between the <code>compile</code> tasks of each module, which illustrates which module depends on which other module's compilation output:</p>
+<p><div style="text-align: center"><img src="VisualizeCompile.svg" alt="VisualizeCompile.svg" style="max-width: 100%; max-height: 500px" /></div></p><h3 id="visualizeplan" class="Styles-hoverBox">visualizePlan<a href="#visualizeplan" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill show visualizePlan moduledefs.compile
+[
+ &quot;.../out/visualizePlan/dest/out.txt&quot;,
+ &quot;.../out/visualizePlan/dest/out.dot&quot;,
+ &quot;.../out/visualizePlan/dest/out.json&quot;,
+ &quot;.../out/visualizePlan/dest/out.png&quot;,
+ &quot;.../out/visualizePlan/dest/out.svg&quot;
+]
+</code></pre>
+<p><code>mill show visualizePlan</code> is similar to <code>mill show visualize</code> except that it shows a graph of the entire build plan, including tasks not directly resolved by the query. Tasks directly resolved are shown with a solid border, and dependencies are shown with a dotted border.</p>
+<p>The above command generates the following diagram:</p>
+<p><div style="text-align: center"><img src="VisualizePlan.svg" alt="VisualizePlan.svg" style="max-width: 100%; max-height: 500px" /></div></p><h3 id="clean" class="Styles-hoverBox">clean<a href="#clean" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill clean
+</code></pre>
+<p><code>clean</code> deletes all the cached outputs of previously executed tasks. It can apply to the entire project, entire modules, or specific tasks.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill clean # clean all outputs
+mill clean foo # clean all outputs for module &#39;foo&#39; (including nested modules)
+mill clean foo.compile # only clean outputs for task &#39;compile&#39; in module &#39;foo&#39;
+mill clean foo.{compile,run}
+mill clean &quot;foo.{compile,run}&quot;
+mill clean foo.compile foo.run
+mill clean _.compile
+mill clean __.compile
+</code></pre><h3 id="search-for-dependency-updates" class="Styles-hoverBox">Search for dependency updates<a href="#search-for-dependency-updates" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill mill.scalalib.Dependency/updates
+</code></pre>
+<p>Mill can search for updated versions of your project's dependencies, if available from your project's configured repositories. Note that it uses heuristics based on common versionning schemes, so it may not work as expected for dependencies with particularly weird version numbers.</p>
+<p>Current limitations: - Only works for <code>JavaModule</code>s (including <code>ScalaModule</code>s, <code>CrossScalaModule</code>s, etc.) and Maven repositories. - Always applies to all modules in the build. - Doesn't apply to <code>$ivy</code> dependencies used in the build definition itself.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill mill.scalalib.Dependency/updates
+mill mill.scalalib.Dependency/updates --allowPreRelease true # also show pre-release versions
+</code></pre><h2 id="intellij-support" class="Styles-hoverBox">IntelliJ Support<a href="#intellij-support" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill supports IntelliJ by default. Use <code>mill mill.scalalib.GenIdea/idea</code> to generate an IntelliJ project config for your build.</p>
+<p>This also configures IntelliJ to allow easy navigate &amp; code-completion within your build file itself.</p><h2 id="the-build-repl" class="Styles-hoverBox">The Build Repl<a href="#the-build-repl" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill -i
+Loading...
+@ foo
+res1: foo.type = ammonite.predef.build#foo:2
+Commands:
+ .runLocal(args: String*)()
+ .run(args: String*)()
+ .runMainLocal(mainClass: String, args: String*)()
+ .runMain(mainClass: String, args: String*)()
+ .console()()
+Targets:
+ .allSources()
+ .artifactId()
+ .artifactName()
+...
+
+@ foo.compile
+res3: mill.package.T[mill.scalalib.CompilationResult] = mill.scalalib.ScalaModule#compile:152
+Inputs:
+ foo.scalaVersion
+ foo.allSources
+ foo.compileDepClasspath
+...
+
+@ foo.compile()
+res2: mill.scalalib.CompilationResult = CompilationResult(
+ root/&#39;Users/&#39;lihaoyi/&#39;Dropbox/&#39;Github/&#39;test/&#39;out/&#39;foo/&#39;compile/&#39;dest/&#39;zinc,
+ PathRef(root/&#39;Users/&#39;lihaoyi/&#39;Dropbox/&#39;Github/&#39;test/&#39;out/&#39;foo/&#39;compile/&#39;dest/&#39;classes, false)
+)
+</code></pre>
+<p>You can run <code>mill -i</code> to open a build REPL; this is a Scala console with your <code>build.sc</code> loaded, which lets you run tasks interactively. The task-running syntax is slightly different from the command-line, but more in-line with how you would depend on tasks from within your build file.</p>
+<p>You can use this REPL to interactively explore your build to see what is available.</p><h2 id="deploying-your-code" class="Styles-hoverBox">Deploying your code<a href="#deploying-your-code" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The two most common things to do once your code is complete is to make an assembly (e.g. for deployment/installation) or publishing (e.g. to Maven Central). Mill comes with both capabilities built in.</p>
+<p>Mill comes built-in with the ability to make assemblies. Given a simple Mill build:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+</code></pre>
+<p>You can make a self-contained assembly via:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill foo.assembly
+
+$ ls -lh out/foo/assembly/dest/out.jar
+-rw-r--r-- 1 lihaoyi staff 5.0M Feb 17 11:14 out/foo/assembly/dest/out.jar
+</code></pre>
+<p>You can then move the <code>out.jar</code> file anywhere you would like, and run it standalone using <code>java</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ java -cp out/foo/assembly/dest/out.jar foo.Example
+Hello World!
+</code></pre>
+<p>To publish to Maven Central, you need to make <code>foo</code> also extend Mill's <code>PublishModule</code> trait:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._, publish._
+
+object foo extends ScalaModule with PublishModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def publishVersion = &quot;0.0.1&quot;
+
+ def pomSettings = PomSettings(
+ description = &quot;Hello&quot;,
+ organization = &quot;com.lihaoyi&quot;,
+ url = &quot;https://github.com/lihaoyi/example&quot;,
+ licenses = Seq(License.MIT),
+ versionControl = VersionControl.github(&quot;lihaoyi&quot;, &quot;example&quot;),
+ developers = Seq(
+ Developer(&quot;lihaoyi&quot;, &quot;Li Haoyi&quot;,&quot;https://github.com/lihaoyi&quot;)
+ )
+ )
+}
+</code></pre>
+<p>You can change the name of the published artifact (artifactId in the Maven POM) by overriding <code>artifactName</code> in the module you want to publish.</p>
+<p>You can download an example project with this layout here:</p>
+<ul>
+ <li><a href="example-2.zip">Example 2</a></li>
+</ul>
+<p>Which you can then publish using the <code>mill foo.publish</code> command, which takes your sonatype credentials (e.g. <code>lihaoyi:foobarbaz</code>) and GPG password as inputs:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">$ mill foo.publish
+Missing arguments: (--sonatypeCreds: String, --release: Boolean)
+
+Arguments provided did not match expected signature:
+
+publish
+ --sonatypeCreds String (format: &quot;username:password&quot;)
+ --gpgPassphrase String (default null)
+ --gpgKeyName String (default null)
+ --signed Boolean (default true)
+ --release Boolean
+</code></pre>
+<p>You also need to specify <code>release</code> as <code>true</code> or <code>false</code>, depending on whether you just want to stage your module on <code>oss.sonatype.org</code> or you want Mill to complete the release process to Maven Central.</p>
+<p>If you are publishing multiple artifacts, you can also use <code>mill mill.scalalib.PublishModule/publishAll</code> as described <a href="http://www.lihaoyi.com/mill/page/common-project-layouts.html#publishing">here</a></p><h2 id="structure-of-the-out-folder" class="Styles-hoverBox">Structure of the <code>out/</code> folder<a href="#structure-of-the-out-folder" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The <code>out/</code> folder contains all the generated files &amp; metadata for your build. It is structured with one folder per <code>Target</code>/<code>Command</code>, that is run, e.g.:</p>
+<ul>
+ <li><code>out/core/compile/</code></li>
+ <li><code>out/main/test/compile/</code></li>
+ <li><code>out/main/test/forkTest/</code></li>
+ <li><code>out/scalalib/compile/</code></li>
+</ul>
+<p>There are also top-level build-related files in the <code>out/</code> folder, prefixed as <code>mill-*</code>. The most useful is <code>mill-profile.json</code>, which logs the tasks run and time taken for the last Mill command you executed. This is very useful if you want to find out exactly what tasks are being run and Mill is being slow.</p>
+<p>Each folder currently contains the following files:</p>
+<ul>
+ <li>
+ <p><code>dest/</code>: a path for the <code>Task</code> to use either as a scratch space, or to place generated files that are returned using <code>PathRef</code>s. <code>Task</code>s should only output files within their given <code>dest/</code> folder (available as <code>T.ctx().dest</code>) to avoid conflicting with other <code>Task</code>s, but files within <code>dest/</code> can be named arbitrarily.</p></li>
+ <li>
+ <p><code>log</code>: the <code>stdout</code>/<code>stderr</code> of the <code>Task</code>. This is also streamed to the console during evaluation.</p></li>
+ <li>
+ <p><code>meta.json</code>: the cache-key and JSON-serialized return-value of the <code>Target</code>/<code>Command</code>. The return-value can also be retrieved via <code>mill show
+ core.compile</code>. Binary blobs are typically not included in <code>meta.json</code>, and instead stored as separate binary files in <code>dest/</code> which are then referenced by <code>meta.json</code> via <code>PathRef</code>s</p></li>
+</ul>
+<p>The <code>out/</code> folder is intentionally kept simplistic and user-readable. If your build is not behaving as you would expect, feel free to poke around the various <code>dest/</code> folders to see what files are being created, or the <code>meta.json</code> files to see what is being returned by a particular task. You can also simply delete folders within <code>out/</code> if you want to force portions of your project to be re-built, e.g. deleting the <code>out/main/</code> or <code>out/main/test/compile/</code> folders.</p><h2 id="overriding-mill-versions" class="Styles-hoverBox">Overriding Mill Versions<a href="#overriding-mill-versions" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Apart from downloading and installing new versions of Mill globally, there are a few ways of selecting/updating your Mill version:</p>
+<ul>
+ <li>Create a <code>.mill-version</code> file to specify the version of Mill you wish to use:</li>
+</ul>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">echo &quot;0.5.0&quot; &gt; .mill-version
+</code></pre>
+<p><code>.mill-version</code> takes precedence over the version of Mill specified in the <code>./mill</code> script.</p>
+<ul>
+ <li>ass in a <code>MILL_VERSION</code> environment variable, e.g.</li>
+</ul>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">MILL_VERSION=0.5.0-3-4faefb mill __.compile
+ ```
+
+or
+</code></pre>
+<p>MILL_VERSION=0.5.0-3-4faefb ./mill __.compile ```</p>
+<p>to override the Mill version manually. This takes precedence over the version specified in <code>./mill</code> or <code>.mill-version</code></p>
+<p>Note that both of these overrides only work for versions 0.5.0 and above.</p><h3 id="development-releases" class="Styles-hoverBox">Development Releases<a href="#development-releases" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>In case you want to try out the latest features and improvements that are currently in master, unstable versions of Mill are <a href="https://github.com/lihaoyi/mill/releases">available</a> as binaries named <code>#.#.#-n-hash</code> linked to the latest tag. Installing the latest unstable release is recommended for bootstrapping mill.</p>
+<p>The easiest way to use a development release is by updating the <a href="#bootstrap-scripts-linuxos-x-only">Bootstrap Script</a>, or <a href="#overriding-mill-versions">Overriding Mill Versions</a> via an environment variable or <code>.mill-version</code> file.</p>
+<p>Come by our <a href="https://gitter.im/lihaoyi/mill">Gitter Channel</a> if you want to ask questions or say hi!</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><div></div><a href="page/configuring-mill.html">Configuring Mill <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/logo-white.svg b/logo-white.svg
new file mode 100644
index 00000000..a681aa9f
--- /dev/null
+++ b/logo-white.svg
@@ -0,0 +1 @@
+<!DOCTYPE html><svg xmlns="http://www.w3.org/2000/svg" height="24" width="24"><polyline points="24,-44.0 0,4.0 0,20.0 24,-28.0" fill="#f8f8f8"></polyline><polyline points="24,-20.0 0,28.0 0,44.0 24,-4.0" fill="#f8f8f8"></polyline><polyline points="24,4.0 0,52.0 0,68.0 24,20.0" fill="#f8f8f8"></polyline></svg> \ No newline at end of file
diff --git a/page/common-project-layouts.html b/page/common-project-layouts.html
new file mode 100644
index 00000000..d816d363
--- /dev/null
+++ b/page/common-project-layouts.html
@@ -0,0 +1,355 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Common Project Layouts</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#common-project-layouts">Common Project Layouts</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#java-project-with-test-suite">Java Project with Test Suite</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#cross-scala-version-modules">Cross Scala-Version Modules</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scalajs-modules">Scala.js Modules</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scala-native-modules">Scala Native Modules</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#sbt-compatible-modules">SBT-Compatible Modules</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#sbt-compatible-cross-scala-version-modules">SBT-Compatible Cross Scala-Version Modules</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#publishing">Publishing</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#example-builds">Example Builds</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#acyclic">Acyclic</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#better-files">Better-Files</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#jawn">Jawn</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#upickle">Upickle</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#ammonite">Ammonite</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Common Project Layouts</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="configuring-mill.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Configuring Mill</a><a href="tasks.html">Tasks <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><h2 id="common-project-layouts" class="Styles-hoverBox">Common Project Layouts<a href="#common-project-layouts" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Earlier, we have shown how to work with the Mill default Scala module layout. Here we will explore some other common project layouts that you may want in your Scala build:</p><h3 id="java-project-with-test-suite" class="Styles-hoverBox">Java Project with Test Suite<a href="#java-project-with-test-suite" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">trait JUnitTests extends TestModule {
+ def testFrameworks = Seq(&quot;com.novocode.junit.JUnitFramework&quot;)
+ def ivyDeps = Agg(ivy&quot;com.novocode:junit-interface:0.11&quot;)
+}
+
+object core extends JavaModule {
+ object test extends Tests with JUnitTests
+}
+object app extends JavaModule {
+ def moduleDeps = Seq(core)
+ object test extends Tests with JUnitTests
+}
+</code></pre>
+<p>This build is a two-module Java project with junit test suites. It expects the following filesystem layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">build.sc
+app/
+ src/hello/
+ Main.java
+ test/src/hello/
+ MyAppTests.java
+core/
+ src/hello/
+ Core.java
+ test/src/hello/
+ MyCoreTests.java
+</code></pre>
+<p>You can then run the junit tests using <code>mill app.test</code> or <code>mill core.test</code>, and configure which exact tests you want to run using the flags defined on the <a href="https://github.com/sbt/junit-interface#junit-interface">JUnit Test Interface</a>.</p>
+<p>For a more more complex, real-world example of a Java build, check out our example build for the popular <a href="https://github.com/ben-manes/caffeine">Caffeine</a> project:</p>
+<ul>
+ <li><a href="https://github.com/lihaoyi/mill/blob/master/integration/test/resources/caffeine/build.sc">Example Build</a></li>
+</ul><h3 id="cross-scala-version-modules" class="Styles-hoverBox">Cross Scala-Version Modules<a href="#cross-scala-version-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._
+import mill.scalalib._
+object foo extends Cross[FooModule](&quot;2.10.6&quot;, &quot;2.11.11&quot;, &quot;2.12.4&quot;)
+class FooModule(val crossScalaVersion: String) extends CrossScalaModule {
+ ...
+ object test extends Tests {
+ ...
+ }
+}
+</code></pre>
+<p>Mill provides a <code>CrossScalaModule</code> template, which can be used with <code>Cross</code> to cross-build Scala modules across different versions of Scala. The default configuration for <code>CrossScalaModule</code> expects a filesystem layout as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">build.sc
+foo/
+ src/
+ src-2.10/
+ src-2.11/
+ src-2.12/
+ test/
+ src/
+ src-2.10/
+ src-2.11/
+ src-2.12/
+</code></pre>
+<p>Code common to all Scala versions lives in <code>src</code>, while code specific to one version lives in <code>src-x.y</code>.</p><h3 id="scalajs-modules" class="Styles-hoverBox">Scala.js Modules<a href="#scalajs-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._
+import mill.scalajslib._
+
+object foo extends ScalaJSModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def scalaJSVersion = &quot;0.6.22&quot;
+}
+</code></pre>
+<p><code>ScalaJSModule</code> is a variant of <code>ScalaModule</code> that builds your code using Scala.js. In addition to the standard <code>foo.compile</code> and <code>foo.run</code> commands (the latter of which runs your code on Node.js, which must be pre-installed) <code>ScalaJSModule</code> also exposes the <code>foo.fastOpt</code> and <code>foo.fullOpt</code> tasks for generating the optimized Javascript file.</p><h3 id="scala-native-modules" class="Styles-hoverBox">Scala Native Modules<a href="#scala-native-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._, scalanativelib._
+
+object hello extends ScalaNativeModule {
+ def scalaVersion = &quot;2.11.12&quot;
+ def scalaNativeVersion = &quot;0.3.8&quot;
+ def logLevel = NativeLogLevel.Info // optional
+ def releaseMode = ReleaseMode.Debug // optional
+}
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
+├── build.sc
+└── hello
+ ├── src
+ │   └── hello
+ │   └── Hello.scala
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// hello/src/hello/Hello.scala
+package hello
+import scalatags.Text.all._
+object Hello{
+ def main(args: Array[String]): Unit = {
+ println(&quot;Hello! &quot; + args.toList)
+ println(div(&quot;one&quot;))
+ }
+}
+</code></pre>
+<p>The normal commands <code>mill hello.compile</code>, <code>mill hello.run</code>, all work. If you want to build a standalone executable, you can use <code>mill show hello.nativeLink</code> to create it.</p>
+<p><code>ScalaNativeModule</code> builds scala sources to executable binaries using <a href="http://www.scala-native.org">Scala Native</a>. You will need to have the <a href="http://www.scala-native.org/en/latest/user/setup.html">relevant parts</a> of the LLVM toolchain installed on your system. Optimized binaries can be built by setting <code>releaseMode</code> (see above) and more verbose logging can be enabled using <code>logLevel</code>. Currently two test frameworks are supported <a href="https://github.com/lihaoyi/utest">utest</a> and <a href="http://www.scalatest.org/">scalatest</a>. Support for <a href="https://www.scalacheck.org/">scalacheck</a> should be possible when the relevant artifacts have been published for scala native.</p>
+<p>Here's a slightly larger example, demonstrating how to use third party dependencies (note the two sets of double-colons <code>::</code> necessary) and a test suite:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._, scalanativelib._
+
+object hello extends ScalaNativeModule {
+ def scalaNativeVersion = &quot;0.3.8&quot;
+ def scalaVersion = &quot;2.11.12&quot;
+ def ivyDeps = Agg(ivy&quot;com.lihaoyi::scalatags::0.6.7&quot;)
+ object test extends Tests{
+ def ivyDeps = Agg(ivy&quot;com.lihaoyi::utest::0.6.3&quot;)
+ def testFrameworks = Seq(&quot;utest.runner.Framework&quot;)
+ }
+}
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
+├── build.sc
+└── hello
+ ├── src
+ │   └── hello
+ │   └── Hello.scala
+ └── test
+ └── src
+ └── HelloTests.scala
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// hello/test/src/HelloTests.scala
+package hello
+import utest._
+import scalatags.Text.all._
+object HelloTests extends TestSuite{
+ val tests = Tests{
+ &#39;pass - {
+ assert(div(&quot;1&quot;).toString == &quot;&lt;div&gt;1&lt;/div&gt;&quot;)
+ }
+ &#39;fail - {
+ assert(123 == 1243)
+ }
+ }
+}
+</code></pre>
+<p>The same <code>mill hello.compile</code> or <code>mill hello.run</code> still work, as does `<code>mill
+hello.test</code> to run the test suite defined here.</p><h3 id="sbt-compatible-modules" class="Styles-hoverBox">SBT-Compatible Modules<a href="#sbt-compatible-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._
+import mill.scalalib._
+
+object foo extends SbtModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+</code></pre>
+<p>These are basically the same as normal <code>ScalaModule</code>s, but configured to follow the SBT project layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">build.sc
+foo/
+ src/
+ main/
+ scala/
+ test/
+ scala/
+</code></pre>
+<p>Useful if you want to migrate an existing project built with SBT without having to re-organize all your files</p><h3 id="sbt-compatible-cross-scala-version-modules" class="Styles-hoverBox">SBT-Compatible Cross Scala-Version Modules<a href="#sbt-compatible-cross-scala-version-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._
+import mill.scalalib._
+object foo extends Cross[FooModule](&quot;2.10.6&quot;, &quot;2.11.11&quot;, &quot;2.12.4&quot;)
+class FooModule(val crossScalaVersion: String) extends CrossSbtModule {
+ ...
+ object test extends Tests {
+ ...
+ }
+}
+</code></pre>
+<p>A <code>CrossSbtModule</code> is a version of <code>CrossScalaModule</code> configured with the SBT project layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">build.sc
+foo/
+ src/
+ main/
+ scala/
+ scala-2.10/
+ scala-2.11/
+ scala-2.12/
+ test/
+ scala/
+ scala-2.10/
+ scala-2.11/
+ scala-2.12/
+</code></pre><h3 id="publishing" class="Styles-hoverBox">Publishing<a href="#publishing" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._
+import mill.scalalib._
+import mill.scalalib.publish._
+object foo extends ScalaModule with PublishModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def publishVersion = &quot;0.0.1&quot;
+ def pomSettings = PomSettings(
+ description = &quot;My first library&quot;,
+ organization = &quot;com.lihaoyi&quot;,
+ url = &quot;https://github.com/lihaoyi/mill&quot;,
+ licenses = Seq(License.MIT),
+ versionControl = VersionControl.github(&quot;lihaoyi&quot;, &quot;mill&quot;),
+ developers = Seq(
+ Developer(&quot;lihaoyi&quot;, &quot;Li Haoyi&quot;,&quot;https://github.com/lihaoyi&quot;)
+ )
+ )
+}
+</code></pre>
+<p>You can make a module publishable by extending <code>PublishModule</code>.</p>
+<p><code>PublishModule</code> then needs you to define a <code>publishVersion</code> and <code>pomSettings</code>. The <code>artifactName</code> defaults to the name of your module (in this case <code>foo</code>) but can be overriden. The <code>organization</code> is defined in <code>pomSettings</code>.</p>
+<p>Once you've mixed in <code>PublishModule</code>, you can publish your libraries to maven central via:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill mill.scalalib.PublishModule/publishAll \
+ lihaoyi:$SONATYPE_PASSWORD \
+ $GPG_PASSWORD \
+ foo.publishArtifacts
+</code></pre>
+<p>This uploads them to <code>oss.sonatype.org</code> where you can log-in and stage/release them manually. You can also pass in the <code>--release true</code> flag to perform the staging/release automatically:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill mill.scalalib.PublishModule/publishAll \
+ lihaoyi:$SONATYPE_PASSWORD \
+ $GPG_PASSWORD \
+ foo.publishArtifacts \
+ --release true
+</code></pre>
+<p>If you want to publish/release multiple modules, you can use the <code>_</code> or <code>__</code> wildcard syntax:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill mill.scalalib.PublishModule/publishAll \
+ lihaoyi:$SONATYPE_PASSWORD \
+ $GPG_PASSWORD \
+ __.publishArtifacts \
+ --release true
+</code></pre><h2 id="example-builds" class="Styles-hoverBox">Example Builds<a href="#example-builds" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill comes bundled with example builds for existing open-source projects, as integration tests and examples:</p><h3 id="acyclic" class="Styles-hoverBox">Acyclic<a href="#acyclic" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><a href="https://github.com/lihaoyi/mill/blob/master/integration/test/resources/acyclic/build.sc#L1">Mill Build</a></li>
+</ul>
+<p>A small single-module cross-build, with few sources, minimal dependencies, and wired up for publishing to Maven Central.</p><h3 id="better-files" class="Styles-hoverBox">Better-Files<a href="#better-files" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><a href="https://github.com/lihaoyi/mill/blob/master/integration/test/resources/better-files/build.sc#L1">Mill Build</a></li>
+</ul>
+<p>A collection of small modules compiled for a single Scala version.</p>
+<p>Also demonstrates how to define shared configuration in a <code>trait</code>, enable Scala compiler flags, and download artifacts as part of the build.</p><h3 id="jawn" class="Styles-hoverBox">Jawn<a href="#jawn" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><a href="https://github.com/lihaoyi/mill/blob/master/integration/test/resources/jawn/build.sc#L1">Mill Build</a></li>
+</ul>
+<p>A collection of relatively small modules, all cross-built across the same few versions of Scala.</p><h3 id="upickle" class="Styles-hoverBox">Upickle<a href="#upickle" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><a href="https://github.com/lihaoyi/mill/blob/master/integration/test/resources/upickle/build.sc#L1">Mill Build</a></li>
+</ul>
+<p>A single cross-platform Scala.js/Scala-JVM module cross-built against multiple versions of Scala, including the setup necessary for publishing to Maven Central.</p><h3 id="ammonite" class="Styles-hoverBox">Ammonite<a href="#ammonite" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><a href="https://github.com/lihaoyi/mill/blob/master/integration/test/resources/ammonite/build.sc#L1">Mill Build</a></li>
+</ul>
+<p>A relatively complex build with numerous submodules, some cross-built across Scala major versions while others are cross-built against Scala minor versions.</p>
+<p>Also demonstrates how to pass one module's compiled artifacts to the <code>run</code>/<code>test</code> commands of another, via their <code>forkEnv</code>.</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="configuring-mill.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Configuring Mill</a><a href="tasks.html">Tasks <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/configuring-mill.html b/page/configuring-mill.html
new file mode 100644
index 00000000..70cff6f3
--- /dev/null
+++ b/page/configuring-mill.html
@@ -0,0 +1,447 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Configuring Mill</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#compilation--execution-flags">Compilation &amp; Execution Flags</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#adding-ivy-dependencies">Adding Ivy Dependencies</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#adding-a-test-suite">Adding a Test Suite</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#custom-test-frameworks">Custom Test Frameworks</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scala-compiler-plugins">Scala Compiler Plugins</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#reformatting-your-code">Reformatting your code</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#common-configuration">Common Configuration</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#global-configuration">Global configuration</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#custom-tasks">Custom Tasks</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#custom-modules">Custom Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#moduletask-names">Module/Task Names</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#overriding-tasks">Overriding Tasks</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#unmanaged-jars">Unmanaged Jars</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#defining-a-main-class">Defining a Main Class</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#mergeexclude-files-from-assembly">Merge/exclude files from assembly</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#downloading-non-maven-jars">Downloading Non-Maven Jars</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Configuring Mill</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="../index.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Intro to Mill</a><a href="common-project-layouts.html">Common Project Layouts <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>You can configure your Mill build in a number of ways:</p><h2 id="compilation--execution-flags" class="Styles-hoverBox">Compilation &amp; Execution Flags<a href="#compilation--execution-flags" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+
+ def scalacOptions = Seq(&quot;-Ydelambdafy:inline&quot;)
+
+ def forkArgs = Seq(&quot;-Xmx4g&quot;)
+
+ def forkEnv = Map(&quot;HELLO_MY_ENV_VAR&quot; -&gt; &quot;WORLD&quot;)
+}
+</code></pre>
+<p>You can pass flags to the Scala compiler via <code>scalacOptions</code>. By default, <code>foo.run</code> runs the compiled code in a subprocess, and you can pass in JVM flags via <code>forkArgs</code> or environment-variables via <code>forkEnv</code>.</p>
+<p>You can also run your code via</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill foo.runLocal
+</code></pre>
+<p>Which runs it in-process within an isolated classloader. This may be faster since you avoid the JVM startup, but does not support <code>forkArgs</code> or <code>forkEnv</code>.</p>
+<p>If you want to pass main-method arguments to <code>run</code> or <code>runLocal</code>, simply pass them after the <code>foo.run</code>/<code>foo.runLocal</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill foo.run arg1 arg2 arg3
+mill foo.runLocal arg1 arg2 arg3
+</code></pre><h2 id="adding-ivy-dependencies" class="Styles-hoverBox">Adding Ivy Dependencies<a href="#adding-ivy-dependencies" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def ivyDeps = Agg(
+ ivy&quot;com.lihaoyi::upickle:0.5.1&quot;,
+ ivy&quot;com.lihaoyi::pprint:0.5.2&quot;,
+ ivy&quot;com.lihaoyi::fansi:0.2.4&quot;,
+ ivy&quot;${scalaOrganization()}:scala-reflect:${scalaVersion()}&quot;
+ )
+}
+</code></pre>
+<p>You can define the <code>ivyDeps</code> field to add ivy dependencies to your module. The <code>ivy&quot;com.lihaoyi::upickle:0.5.1&quot;</code> syntax (with <code>::</code>) represents Scala dependencies; for Java dependencies you would use a single <code>:</code> e.g. <code>ivy&quot;com.lihaoyi:upickle:0.5.1&quot;</code>. If you have dependencies cross-published against the full Scala version (eg. <code>2.12.4</code> instead of just <code>2.12</code>), you can use <code>:::</code> as in <code>ivy&quot;org.scalamacros:::paradise:2.1.1&quot;</code>.</p>
+<p>To select the test-jars from a dependency use the following syntax: <code>ivy&quot;org.apache.spark::spark-sql:2.4.0;classifier=tests</code>.</p>
+<p>By default these are resolved from maven central, but you can add your own resolvers by overriding the <code>repositories</code> definition in the module:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import coursier.maven.MavenRepository
+
+def repositories = super.repositories ++ Seq(
+ MavenRepository(&quot;https://oss.sonatype.org/content/repositories/releases&quot;)
+)
+</code></pre>
+<p>To add custom resolvers to the initial bootstrap of the build, you can create a custom <code>ZincWorkerModule</code>, and override the <code>zincWorker</code> method in your <code>ScalaModule</code> by pointing it to that custom object:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import coursier.maven.MavenRepository
+
+object CustomZincWorkerModule extends ZincWorkerModule {
+ def repositories() = super.repositories ++ Seq(
+ MavenRepository(&quot;https://oss.sonatype.org/content/repositories/releases&quot;)
+ )
+}
+
+object YourBuild extends ScalaModule {
+ def zincWorker = CustomZincWorkerModule
+ // ... rest of your build definitions
+}
+</code></pre><h2 id="adding-a-test-suite" class="Styles-hoverBox">Adding a Test Suite<a href="#adding-a-test-suite" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+
+ object test extends Tests {
+ def ivyDeps = Agg(ivy&quot;com.lihaoyi::utest:0.6.0&quot;)
+ def testFrameworks = Seq(&quot;utest.runner.Framework&quot;)
+ }
+}
+</code></pre>
+<p>You can define a test suite by creating a nested module extending <code>Tests</code>, and specifying the ivy coordinates and name of your test framework. This expects the tests to be laid out as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">build.sc
+foo/
+ src/
+ Main.scala
+ resources/
+ ...
+ test/
+ src/
+ MainTest.scala
+ resources/
+ ...
+out/
+ foo/
+ ...
+ test/
+ ...
+</code></pre>
+<p>The above example can be run via</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill foo.test
+</code></pre>
+<p>By default, tests are run in a subprocess, and <code>forkArg</code> and <code>forkEnv</code> can be overriden to pass JVM flags &amp; environment variables. You can also use</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill foo.test.testLocal
+</code></pre>
+<p>To run tests in-process in an isolated classloader.</p>
+<p>If you want to pass any arguments to the test framework, simply put them after <code>foo.test</code> in the command line. e.g. <a href="https://github.com/lihaoyi/utest">uTest</a> lets you pass in a selector to decide which test to run, which in Mill would be:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill foo.test foo.MyTestSuite.testCaseName
+</code></pre>
+<p>You can define multiple test suites if you want, e.g.:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+
+ object test extends Tests {
+ def ivyDeps = Agg(ivy&quot;com.lihaoyi::utest:0.6.0&quot;)
+ def testFrameworks = Seq(&quot;utest.runner.Framework&quot;)
+ }
+ object integration extends Tests {
+ def ivyDeps = Agg(ivy&quot;com.lihaoyi::utest:0.6.0&quot;)
+ def testFrameworks = Seq(&quot;utest.runner.Framework&quot;)
+ }
+}
+</code></pre>
+<p>Each of which will expect their sources to be in their respective <code>foo/test</code> and <code>foo/integration</code> folder.</p>
+<p><code>Tests</code> modules are <code>ScalaModule</code>s like any other, and all the same configuration options apply.</p><h2 id="custom-test-frameworks" class="Styles-hoverBox">Custom Test Frameworks<a href="#custom-test-frameworks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def ivyDeps = Agg(ivy&quot;org.scalatest::scalatest:3.0.4&quot;)
+ def testFrameworks = Seq(&quot;org.scalatest.tools.Framework&quot;)
+}
+</code></pre>
+<p>Integrating with test frameworks like Scalatest is simply a matter of adding it to <code>ivyDeps</code> and specifying the <code>testFrameworks</code> you want to use. After that you can <a href="#adding-a-test-suite">add a test suite</a> and <code>mill foo.test</code> as usual, passing args to the test suite via <code>mill foo.test arg1 arg2 arg3</code></p><h2 id="scala-compiler-plugins" class="Styles-hoverBox">Scala Compiler Plugins<a href="#scala-compiler-plugins" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+
+ def compileIvyDeps = Agg(ivy&quot;com.lihaoyi::acyclic:0.1.7&quot;)
+ def scalacOptions = Seq(&quot;-P:acyclic:force&quot;)
+ def scalacPluginIvyDeps = Agg(ivy&quot;com.lihaoyi::acyclic:0.1.7&quot;)
+}
+</code></pre>
+<p>You can use Scala compiler plugins by setting <code>scalacPluginIvyDeps</code>. The above example also adds the plugin to <code>compileIvyDeps</code>, since that plugin's artifact is needed on the compilation classpath (though not at runtime).</p><h2 id="reformatting-your-code" class="Styles-hoverBox">Reformatting your code<a href="#reformatting-your-code" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill supports code formatting via <a href="https://scalameta.org/scalafmt/">scalafmt</a> out of the box.</p>
+<p>To have a formatting per-module you need to make your module extend <code>mill.scalalib.scalafmt.ScalafmtModule</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._, scalafmt._
+
+object foo extends ScalaModule with ScalafmtModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+</code></pre>
+<p>Now you can reformat code with <code>mill foo.reformat</code> command.</p>
+<p>You can also reformat your project's code globally with <code>mill mill.scalalib.scalafmt.ScalafmtModule/reformatAll __.sources</code> command. It will reformat all sources that matches <code>__.sources</code> query.</p>
+<p>If you add a <code>.scalafmt.conf</code> file at the root of you project, it will be used to configure formatting. It can contain a <code>version</code> key to specify the scalafmt version used to format your code. See the <a href="https://scalameta.org/scalafmt/docs/configuration.html">scalafmt configuration documentation</a> for details.</p><h2 id="common-configuration" class="Styles-hoverBox">Common Configuration<a href="#common-configuration" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+trait CommonModule extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+
+object foo extends CommonModule
+object bar extends CommonModule {
+ def moduleDeps = Seq(foo)
+}
+</code></pre>
+<p>You can extract out configuration common to multiple modules into a <code>trait</code> that those modules extend. This is useful for providing convenience &amp; ensuring consistent configuration: every module often has the same scala-version, uses the same testing framework, etc. and all that can be extracted out into the <code>trait</code>.</p><h2 id="global-configuration" class="Styles-hoverBox">Global configuration<a href="#global-configuration" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill builds on ammonite which allows you to <a href="http://ammonite.io/#ScriptPredef">define global configuration</a>. Depending on how you start mill 2 different files will be loaded. For interactive mode it's <code>~/.mill/ammonite/predef.sc</code> and from the command line it's <code>~/.mill/ammonite/predefScript.sc</code>. You might want to create a symlink from one to the other to avoid duplication.</p>
+<p>Example <code>~/.mill/ammonite/predef.sc</code></p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">val nexusUser = &quot;myuser&quot;
+val nexusPassword = &quot;mysecret&quot;
+</code></pre>
+<p>Everything declared in the above file will be available to any build you run.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala"> def repositories = super.repositories ++ Seq(
+ // login and pass are globally configured
+ MavenRepository(&quot;https://nexus.mycompany.com/repository/maven-releases&quot;, authentication = Some(coursier.core.Authentication(nexusUser, nexusPassword)))
+ )
+</code></pre><h2 id="custom-tasks" class="Styles-hoverBox">Custom Tasks<a href="#custom-tasks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+}
+
+def lineCount = T {
+
+ foo.sources().flatMap(ref =&gt; os.walk(ref.path)).filter(_.isFile).flatMap(read.lines).size
+}
+
+def printLineCount() = T.command {
+ println(lineCount())
+}
+</code></pre>
+<p>You can define new cached Targets using the <code>T {...}</code> syntax, depending on existing Targets e.g. <code>foo.sources</code> via the <code>foo.sources()</code> syntax to extract their current value, as shown in <code>lineCount</code> above. The return-type of a Target has to be JSON-serializable (using <a href="https://github.com/lihaoyi/upickle">uPickle</a>) and the Target is cached when first run until its inputs change (in this case, if someone edits the <code>foo.sources</code> files which live in <code>foo/src</code>. Cached Targets cannot take parameters.</p>
+<p>You can print the value of your custom target using <code>show</code>, e.g.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill show lineCount
+</code></pre>
+<p>You can define new un-cached Commands using the <code>T.command {...}</code> syntax. These are un-cached and re-evaluate every time you run them, but can take parameters. Their return type needs to be JSON-writable as well, or <code>(): Unit</code> if you want to return nothing.</p>
+<p>Your custom targets can depend on each other using the <code>def bar = T {... foo()
+...}</code> syntax, and you can create arbitrarily long chains of dependent targets. Mill will handle the re-evaluation and caching of the targets' output for you, and will provide you a <code>T.ctx().dest</code> folder for you to use as scratch space or to store files you want to return.</p>
+<p>Custom targets and commands can contain arbitrary code. Whether you want to download files (e.g. using <code>mill.modules.Util.download</code>), shell-out to Webpack to compile some Javascript, generate sources to feed into a compiler, or create some custom jar/zip assembly with the files you want (e.g. using <code>mill.modules.Jvm.createJar</code>), all of these can simply be custom targets with your code running in the <code>T {...}</code> block.</p><h2 id="custom-modules" class="Styles-hoverBox">Custom Modules<a href="#custom-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object qux extends Module {
+ object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ }
+ object bar extends ScalaModule {
+ def moduleDeps = Seq(foo)
+ def scalaVersion = &quot;2.12.4&quot;
+ }
+}
+</code></pre>
+<p>Not every Module needs to be a <code>ScalaModule</code>; sometimes you just want to group things together for neatness. In the above example, you can run <code>foo</code> and <code>bar</code> namespaced inside <code>qux</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill qux.foo.compile
+mill qux.bar.run
+</code></pre>
+<p>You can also define your own module traits, with their own set of custom tasks, to represent other things e.g. Javascript bundles, docker image building,:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+trait MySpecialModule extends Module {
+ ...
+}
+object foo extends MySpecialModule
+object bar extends MySpecialModule
+</code></pre><h2 id="moduletask-names" class="Styles-hoverBox">Module/Task Names<a href="#moduletask-names" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import mill.scalalib._
+
+object `hyphenated-module` extends Module {
+ def `hyphenated-target` = T{
+ println(&quot;This is a hyphenated target in a hyphenated module.&quot;)
+ }
+}
+
+object unhyphenatedModule extends Module {
+ def unhyphenated_target = T{
+ println(&quot;This is an unhyphenated target in an unhyphenated module.&quot;)
+ }
+ def unhyphenated_target2 = T{
+ println(&quot;This is the second unhyphenated target in an unhyphenated module.&quot;)
+ }
+}
+</code></pre>
+<p>Mill modules and tasks may be composed of any of the following characters types:</p>
+<ul>
+ <li>Alphanumeric (A-Z, a-z, and 0-9)</li>
+ <li>Underscore (_)</li>
+ <li>Hyphen (-)</li>
+</ul>
+<p>Due to Scala naming restrictions, module and task names with hyphens must be surrounded by back-ticks (`).</p>
+<p>Using hyphenated names at the command line is unaffected by these restrictions.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill hyphenated-module.hyphenated-target
+mill unhyphenatedModule.unhyphenated_target
+mill unhyphenatedModule.unhyphenated_target2
+</code></pre><h2 id="overriding-tasks" class="Styles-hoverBox">Overriding Tasks<a href="#overriding-tasks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def compile = T {
+ println(&quot;Compiling...&quot;)
+ super.compile()
+ }
+ def run(args: String*) = T.command {
+ println(&quot;Running...&quot; + args.mkString(&quot; &quot;))
+ super.run(args:_*)
+ }
+}
+</code></pre>
+<p>You can re-define targets and commands to override them, and use <code>super</code> if you want to refer to the originally defined task. The above example shows how to override <code>compile</code> and <code>run</code> to add additional logging messages, but you can also override <code>ScalaModule#generatedSources</code> to feed generated code to your compiler, <code>ScalaModule#prependShellScript</code> to make your assemblies executable, or <code>ScalaModule#console</code> to use the Ammonite REPL instead of the normal Scala REPL.</p>
+<p>In Mill builds the <code>override</code> keyword is optional.</p><h2 id="unmanaged-jars" class="Styles-hoverBox">Unmanaged Jars<a href="#unmanaged-jars" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def unmanagedClasspath = T {
+ if (!ammonite.ops.exists(millSourcePath / &quot;lib&quot;)) Agg()
+ else Agg.from(ammonite.ops.ls(millSourcePath / &quot;lib&quot;).map(PathRef(_)))
+ }
+}
+</code></pre>
+<p>You can override <code>unmanagedClasspath</code> to point it at any jars you place on the filesystem, e.g. in the above snippet any jars that happen to live in the <code>foo/lib/</code> folder.</p><h2 id="defining-a-main-class" class="Styles-hoverBox">Defining a Main Class<a href="#defining-a-main-class" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def mainClass = Some(&quot;foo.bar.Baz&quot;)
+}
+</code></pre>
+<p>Mill's <code>foo.run</code> by default will discover which main class to run from your compilation output, but if there is more than one or the main class comes from some library you can explicitly specify which one to use. This also adds the main class to your <code>foo.jar</code> and <code>foo.assembly</code> jars.</p><h2 id="mergeexclude-files-from-assembly" class="Styles-hoverBox">Merge/exclude files from assembly<a href="#mergeexclude-files-from-assembly" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>When you make a runnable jar of your project with <code>assembly</code> command, you may want to exclude some files from a final jar (like signature files, and manifest files from library jars), and merge duplicated files (for instance <code>reference.conf</code> files from library dependencies).</p>
+<p>By default mill excludes all <code>*.sf</code>, <code>*.dsa</code>, <code>*.rsa</code>, and <code>META-INF/MANIFEST.MF</code> files from assembly, and concatenates all <code>reference.conf</code> files. You can also define your own merge/exclude rules.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+import mill.modules.Assembly._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def assemblyRules = Seq(
+ Rule.Append(&quot;application.conf&quot;), // all application.conf files will be concatenated into single file
+ Rule.AppendPattern(&quot;.*\\.conf&quot;), // all *.conf files will be concatenated into single file
+ Rule.ExcludePattern(&quot;*.temp&quot;) // all *.temp files will be excluded from a final jar
+ )
+}
+</code></pre>
+<p>To exclude Scala library from assembly</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+import mill.modules.Assembly._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+
+ def scalaLibraryIvyDeps = T { Agg.empty }
+}
+</code></pre><h2 id="downloading-non-maven-jars" class="Styles-hoverBox">Downloading Non-Maven Jars<a href="#downloading-non-maven-jars" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, scalalib._
+
+object foo extends ScalaModule {
+ def scalaVersion = &quot;2.12.4&quot;
+ def unmanagedClasspath = Agg(
+ mill.modules.Util.download(
+ &quot;https://github.com/williamfiset/FastJavaIO/releases/download/v1.0/fastjavaio.jar&quot;,
+ &quot;fastjavaio.jar&quot;
+ )
+ )
+}
+</code></pre>
+<p>You can also override <code>unmanagedClasspath</code> to point it at jars that you want to download from arbitrary URLs. Note that targets like <code>unmanagedClasspath</code> are cached, so your jar is downloaded only once and re-used indefinitely after that.</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="../index.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Intro to Mill</a><a href="common-project-layouts.html">Common Project Layouts <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/contrib-modules.html b/page/contrib-modules.html
new file mode 100644
index 00000000..22abad5e
--- /dev/null
+++ b/page/contrib-modules.html
@@ -0,0 +1,649 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Contrib Modules</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#bloop">Bloop</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#mix-in">Mix-in</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#note-regarding-metals">Note regarding metals</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#note-regarding-current-mill-support-in-bloop">Note regarding current mill support in bloop</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#buildinfo">BuildInfo</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration-options">Configuration options</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#docker">Docker</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration">Configuration</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#flyway">Flyway</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#play-framework">Play Framework</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-the-plugin">Using the plugin</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-playmodule">Using PlayModule</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-playapimodule">Using PlayApiModule</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#play-configuration-options">Play configuration options</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#additional-play-libraries">Additional play libraries</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#commands-equivalence">Commands equivalence</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-singlemodule">Using SingleModule</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scalapb">ScalaPB</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration-options">Configuration options</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scoverage">Scoverage</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#testng">TestNG</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#tut">Tut</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration-options">Configuration options</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#twirl">Twirl</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#twirl-configuration-options">Twirl configuration options</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#details">Details</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#example">Example</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Contrib Modules</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="mill-internals.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Mill Internals</a><a href="thirdparty-modules.html">Thirdparty Modules <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>The plugins in this section are developed/maintained in the mill git tree.</p>
+<p>When using one of these, it is important that the versions you load match your mill version. To facilitate this, Mill will automatically replace the <code>$MILL_VERSION</code> literal in your ivy imports with the correct value.</p>
+<p>For instance :</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import $ivy.`com.lihaoyi::mill-contrib-bloop:$MILL_VERSION`
+</code></pre><h2 id="bloop" class="Styles-hoverBox">Bloop<a href="#bloop" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>This plugin generates <a href="https://scalacenter.github.io/bloop/">bloop</a> configuration from your build file, which lets you use the bloop CLI for compiling, and makes your scala code editable in <a href="https://scalameta.org/metals/">Metals</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc (or any other .sc file it depends on, including predef)
+import $ivy.`com.lihaoyi::mill-contrib-bloop:$MILL_VERSION`
+</code></pre>
+<p>Then in your terminal :</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">&gt; mill mill.contrib.Bloop/install
+</code></pre>
+<p>It generate correct bloop config for any <code>JavaModule</code>, <code>ScalaModule</code>, <code>ScalaJsModule</code> or <code>ScalaNativeModule</code> under the <code>.bloop</code> folder</p><h3 id="mix-in" class="Styles-hoverBox">Mix-in<a href="#mix-in" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>You can mix-in the <code>Bloop.Module</code> trait with any JavaModule to quickly access the deserialised configuration for that particular module:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import mill.scalalib._
+import mill.contrib.Bloop
+
+object MyModule extends ScalaModule with Bloop.Module {
+ def myTask = T { bloop.config() }
+}
+</code></pre><h3 id="note-regarding-metals" class="Styles-hoverBox">Note regarding metals<a href="#note-regarding-metals" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Generating the bloop config should be enough for metals to pick it up and for features to start working in vscode (or the bunch of other editors metals supports). However, note that this applies only to your project sources. Your mill/ammonite related <code>.sc</code> files are not yet supported by metals.</p>
+<p>The generated bloop config references the semanticDB compiler plugin required by metals to function. If need be, the version of semanticDB can be overriden by extending <code>mill.contrib.bloop.BloopImpl</code> in your own space.</p><h3 id="note-regarding-current-mill-support-in-bloop" class="Styles-hoverBox">Note regarding current mill support in bloop<a href="#note-regarding-current-mill-support-in-bloop" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The mill-bloop integration currently present in the <a href="https://github.com/scalacenter/bloop/blob/master/integrations/mill-bloop/src/main/scala/bloop/integrations/mill/MillBloop.scala#L10">bloop codebase</a> will be deprecated in favour of this implementation.</p><h2 id="buildinfo" class="Styles-hoverBox">BuildInfo<a href="#buildinfo" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Generate scala code from your buildfile. This plugin generates a single object containing information from your build.</p>
+<p>To declare a module that uses BuildInfo you must extend the <code>mill.contrib.buildinfo.BuildInfo</code> trait when defining your module.</p>
+<p>Quickstart:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import $ivy.`com.lihaoyi::mill-contrib-buildinfo:$MILL_VERSION`
+import mill.contrib.buildinfo.BuildInfo
+
+object project extends BuildInfo {
+ val name = &quot;poject-name&quot;
+ def buildInfoMembers: T[Map[String, String]] = T {
+ Map(
+ &quot;name&quot; -&gt; name),
+ &quot;scalaVersion&quot; -&gt; scalaVersion()
+ )
+ }
+}
+</code></pre><h3 id="configuration-options" class="Styles-hoverBox">Configuration options<a href="#configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li>
+ <p><code>def buildInfoMembers: T[Map[String, String]]</code> The map containing all member names and values for the generated info object.</p></li>
+ <li>
+ <p><code>def buildInfoObjectName: String</code>, default: <code>BuildInfo</code> The name of the object which contains all the members from <code>buildInfoMembers</code>.</p></li>
+ <li>
+ <p><code>def buildInfoPackageName: Option[String]</code>, default: <code>None</code> The package name of the object.</p></li>
+</ul><h2 id="docker" class="Styles-hoverBox">Docker<a href="#docker" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Automatically build docker images from your mill project.</p>
+<p>Requires the docker CLI to be installed.</p>
+<p>In the simplest configuration just extend <code>DockerModule</code> and declare a <code>DockerConfig</code> object.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._
+
+import ivy`com.lihaoyi::mill-contrib-docker:VERSION`
+import contrib.docker.DockerModule
+
+object foo extends JavaModule with DockerModule {
+ object docker extends DockerConfig
+}
+</code></pre>
+<p>Then</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">$ mill foo.docker.build
+$ docker run foo
+</code></pre><h3 id="configuration" class="Styles-hoverBox">Configuration<a href="#configuration" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Configure the image by overriding tasks in the <code>DockerConfig</code> object</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object docker extends DockerConfig {
+ // Override tags to set the output image name
+ def tags = List(&quot;aws_account_id.dkr.ecr.region.amazonaws.com/hello-repository&quot;)
+
+ def baseImage = &quot;openjdk:11&quot;
+
+ // Configure whether the docker build should check the remote registry for a new version of the base image before building.
+ // By default this is true if the base image is using a latest tag
+ def pullBaseImage = true
+}
+</code></pre>
+<p>Run mill in interactive mode to see the docker client output, like <code>mill -i foo.docker.build</code>.</p><h2 id="flyway" class="Styles-hoverBox">Flyway<a href="#flyway" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Enables you to configure and run <a href="https://flywaydb.org/">Flyway</a> commands from your mill build file. The flyway module currently supports the most common flyway use cases with file based migrations.</p>
+<p>Configure flyway by overriding settings in your module. For example</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+
+import mill._, scalalib._
+
+import ivy`com.lihaoyi::mill-contrib-flyway:$MILL_VERSION`
+import contrib.flyway.FlywayModule
+
+object foo extends ScalaModule with FlywayModule {
+ def scalaVersion = &quot;2.12.8&quot;
+
+ //region flyway
+ def flywayUrl = &quot;jdbc:postgresql:myDb&quot; // required
+ def flywayDriverDeps = Agg(ivy&quot;org.postgresql:postgresql:42.2.5&quot;) // required
+ def flywayUser = &quot;postgres&quot; // optional
+ // def flywayPassword = &quot;&quot; // optional
+ //endregion
+}
+</code></pre>
+<p>Flyway will look for migration files in <code>db/migration</code> in all resources folders by default. This should work regardless of if you are using a mill or sbt project layout.</p>
+<p>You can then run common flyway commands like</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">mill foo.flywayClean
+mill foo.flywayInfo
+mill foo.flywayMigrate
+</code></pre>
+<blockquote>
+ <p>REMINDER: You should never hard-code credentials or check them into a version control system. You should write some code to populate the settings for flyway instead. For example <code>def flywayPassword = T.input(T.ctx().env(&quot;FLYWAY_PASSWORD&quot;))</code></p>
+</blockquote><h2 id="play-framework" class="Styles-hoverBox">Play Framework<a href="#play-framework" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>This module adds basic Play Framework support to mill:</p>
+<ul>
+ <li>configures mill for Play default directory layout,</li>
+ <li>integrates the Play routes compiler,</li>
+ <li>provides helpers for commonly used framework libraries,</li>
+ <li>optionally: integrates the Twirl template engine,</li>
+ <li>optionally: configures mill for single module play applications.</li>
+</ul>
+<p>There is no specific Play Java support, building a Play Java application will require a bit of customization (mostly adding the proper dependencies).</p><h3 id="using-the-plugin" class="Styles-hoverBox">Using the plugin<a href="#using-the-plugin" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>There are 2 base modules and 2 helper traits in this plugin, all of which can be found in <code>mill.playlib</code>.</p>
+<p>The base modules:</p>
+<ul>
+ <li><code>PlayModule</code> applies the default Play configuration (layout, dependencies, routes compilation, Twirl compilation and Akka HTTP server)</li>
+ <li><code>PlayApiModule</code> applies the default Play configuration without <code>Twirl</code> templating. This is useful if your Play app is a pure API server or if you want to use a different templating engine.</li>
+</ul>
+<p>The two helper traits:</p>
+<ul>
+ <li><code>SingleModule</code> can be useful to configure mill for a single module Play application such as the <a href="https://github.com/playframework/play-scala-seed.g8">play-scala-seed project</a>. Mill is multi-module by default and requires a bit more configuration to have source, resource, and test directories at the top level alongside the <code>build.sc</code> file. This trait takes care of that (See <a href="#using-singlemodule">Using SingleModule</a> below).</li>
+ <li><code>RouterModule</code> allows you to use the Play router without the rest of the configuration (see <a href="#using-the-router-module-directly">Using the router module directly</a>.)</li>
+</ul><h3 id="using-playmodule" class="Styles-hoverBox">Using <code>PlayModule</code><a href="#using-playmodule" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>In order to use the <code>PlayModule</code> for your application, you need to provide the scala, Play and Twirl versions. You also need to define your own test object which extends the provided <code>PlayTests</code> trait.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+
+object core extends PlayModule {
+ //config
+ override def scalaVersion= T{&quot;2.12.8&quot;}
+ override def playVersion= T{&quot;2.7.0&quot;}
+ override def twirlVersion= T{&quot;1.4.0&quot;}
+
+ object test extends PlayTests
+}
+</code></pre>
+<p>Using the above definition, your build will be configured to use the default Play layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
+├── build.sc
+└── core
+ ├── app
+ │   ├── controllers
+ │   └── views
+ ├── conf
+ │   └── application.conf
+ │   └── routes
+ │   └── ...
+ ├── logs
+ ├── public
+ │   ├── images
+ │   ├── javascripts
+ │   └── stylesheets
+ └── test
+ └── controllers
+</code></pre>
+<p>The following compile dependencies will automatically be added to your build:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">ivy&quot;com.typesafe.play::play:${playVersion()}&quot;,
+ivy&quot;com.typesafe.play::play-guice:${playVersion()}&quot;,
+ivy&quot;com.typesafe.play::play-server:${playVersion()}&quot;,
+ivy&quot;com.typesafe.play::play-logback:${playVersion()}&quot;
+</code></pre>
+<p>Scala test will be setup as the default test framework and the following test dependencies will be added (the actual version depends on the version of Play you are pulling <code>2.6.x</code> or <code>2.7.x</code>):</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">ivy&quot;org.scalatestplus.play::scalatestplus-play::4.0.1&quot;
+</code></pre>
+<p>In order to have a working <code>start</code> command the following runtime dependency is also added:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">ivy&quot;com.typesafe.play::play-akka-http-server:${playVersion()}&quot;
+</code></pre><h3 id="using-playapimodule" class="Styles-hoverBox">Using <code>PlayApiModule</code><a href="#using-playapimodule" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The <code>PlayApiModule</code> trait behaves the same as the <code>PlayModule</code> trait but it won't process .scala .html files and you don't need to define the `twirlVersion:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+
+object core extends PlayApiModule {
+ //config
+ override def scalaVersion= T{&quot;2.12.8&quot;}
+ override def playVersion= T{&quot;2.7.0&quot;}
+
+ object test extends PlayTests
+}
+</code></pre><h3 id="play-configuration-options" class="Styles-hoverBox">Play configuration options<a href="#play-configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The Play modules themselves don't have specific configuration options at this point but the <a href="#router-configuration-options">router module configuration options</a> and the <a href="#twirl-configuration-options">Twirl module configuration options</a> are applicable.</p><h3 id="additional-play-libraries" class="Styles-hoverBox">Additional play libraries<a href="#additional-play-libraries" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The following helpers are available to provide additional Play Framework dependencies:</p>
+<ul>
+ <li><code>core()</code> - added by default ,</li>
+ <li><code>guice()</code> - added by default,</li>
+ <li><code>server()</code> - added by default,</li>
+ <li><code>logback()</code> - added by default,</li>
+ <li><code>evolutions()</code> - optional,</li>
+ <li><code>jdbc()</code> - optional,</li>
+ <li><code>filters()</code> - optional,</li>
+ <li><code>ws()</code> - optional,</li>
+ <li><code>caffeine()</code> - optional.</li>
+</ul>
+<p>If you want to add an optional library using the helper you can do so by overriding <code>ivyDeps</code> like in the following example build:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+
+object core extends PlayApiModule {
+ //config
+ override def scalaVersion= T{&quot;2.12.8&quot;}
+ override def playVersion= T{&quot;2.7.0&quot;}
+
+ object test extends PlayTests
+
+ override def ivyDeps = T{ super.ivyDeps() ++ Agg(ws(), filters()) }
+}
+</code></pre><h3 id="commands-equivalence" class="Styles-hoverBox">Commands equivalence<a href="#commands-equivalence" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Mill commands are targets on a named build. For example if your build is called <code>core</code>:</p>
+<ul>
+ <li>compile: <code>core.compile</code></li>
+ <li>run: <em>NOT Implemented yet</em>. It can be approximated with <code>mill -w core.runBackground</code> but this starts a server in <em>PROD</em> mode which:</li>
+ <li>doesn't do any kind of classloading magic (meaning potentially slower restarts)</li>
+ <li>returns less detailed error messages (no source code extract and line numbers)</li>
+ <li>can sometimes fail because of a leftover RUNNING_PID file</li>
+ <li>start: <code>core.start</code> or <code>core.run</code> both start the server in <em>PROD</em> mode.</li>
+ <li>test: <code>core.test</code></li>
+ <li>dist: <em>NOT Implemented yet</em>. However you can use the equivalent <code>core.assembly</code> command to get a runnable fat jar of the project. The packaging is slightly different but should be find for a production deployment.</li>
+</ul><h3 id="using-singlemodule" class="Styles-hoverBox">Using <code>SingleModule</code><a href="#using-singlemodule" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The <code>SingleModule</code> trait allows you to have the build descriptor at the same level as the source code on the filesystem. You can move from there to a multi-module build either by refactoring your directory layout into multiple subdirectories or by using mill's nested modules feature.</p>
+<p>Looking back at the sample build definition in <a href="#using-playmodule">Using PlayModule</a>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+
+object core extends PlayModule {
+ //config
+ override def scalaVersion= T{&quot;2.12.8&quot;}
+ override def playVersion= T{&quot;2.7.0&quot;}
+ override def twirlVersion= T{&quot;1.4.0&quot;}
+
+ object test extends PlayTests
+}
+</code></pre>
+<p>The directory layout was:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
+├── build.sc
+└── core
+ ├── app
+ │   ├── controllers
+ │   └── views
+ ├── conf
+ │   └── application.conf
+ │   └── routes
+ │   └── ...
+ ├── logs
+ ├── public
+ │   ├── images
+ │   ├── javascripts
+ │   └── stylesheets
+ └── test
+ └── controllers
+</code></pre>
+<p>by mixing in the <code>SingleModule</code> trait in your build:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+
+object core extends PlayModule with SingleModule {
+ //config
+ override def scalaVersion= T{&quot;2.12.8&quot;}
+ override def playVersion= T{&quot;2.7.0&quot;}
+ override def twirlVersion= T{&quot;1.4.0&quot;}
+
+ object test extends PlayTests
+}
+</code></pre>
+<p>the layout becomes:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
+└── core
+ ├── build.sc
+ ├── app
+ │   ├── controllers
+ │   └── views
+ ├── conf
+ │   └── application.conf
+ │   └── routes
+ │   └── ...
+ ├── logs
+ ├── public
+ │   ├── images
+ │   ├── javascripts
+ │   └── stylesheets
+ └── test
+ └── controllers
+</code></pre><h4 id="using-the-router-module-directly" class="Styles-hoverBox">Using the router module directly<a href="#using-the-router-module-directly" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h4>
+<p>If you want to use the router module in a project which doesn't use the default Play layout, you can mix-in the <code>mill.playlib.routesModule</code> trait directly when defining your module. Your app must define <code>playVersion</code> and <code>scalaVersion</code>.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+
+object app extends ScalaModule with RouterModule {
+ def playVersion= T{&quot;2.7.0&quot;}
+ def scalaVersion= T{&quot;2.12.8&quot;}
+}
+</code></pre><h5 id="router-configuration-options" class="Styles-hoverBox">Router Configuration options<a href="#router-configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h5>
+<ul>
+ <li><code>def playVersion: T[String]</code> (mandatory) - The version of Play to use to compile the routes file.</li>
+ <li><code>def scalaVersion: T[String]</code> - The scalaVersion in use in your project.</li>
+ <li><code>def routes: Sources</code> - The directory which contains your route files. (Defaults to : <code>routes/</code>)</li>
+ <li><code>def routesAdditionalImport: Seq[String]</code> - Additional imports to use in the generated routers. (Defaults to <code>Seq(&quot;controllers.Assets.Asset&quot;, &quot;play.libs.F&quot;)</code></li>
+ <li><code>def generateForwardsRouter: Boolean = true</code> - Enables the forward router generation.</li>
+ <li><code>def generateReverseRouter: Boolean = true</code> - Enables the reverse router generation.</li>
+ <li><code>def namespaceReverseRouter: Boolean = false</code> - Enables the namespacing of reverse routers.</li>
+ <li><code>def generatorType: RouteCompilerType = RouteCompilerType.InjectedGenerator</code> - The routes compiler type, one of RouteCompilerType.InjectedGenerator or RouteCompilerType.StaticGenerator</li>
+</ul><h5 id="details" class="Styles-hoverBox">Details<a href="#details" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h5>
+<p>The following filesystem layout is expected by default:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
+├── app
+│   └── routes
+│   └── routes
+└── build.sc
+</code></pre>
+<p><code>RouterModule</code> adds the <code>compileRouter</code> task to the module:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">mill app.compileRouter
+</code></pre>
+<p>(it will be automatically run whenever you compile your module)</p>
+<p>This task will compile <code>routes</code> templates into the <code>out/app/compileRouter/dest</code> directory. This directory must be added to the generated sources of the module to be compiled and made accessible from the rest of the code. This is done by default in the trait, but if you need to have a custom override for <code>generatedSources</code> you can get the list of files from <code>routerClasses</code></p>
+<p>To add additional imports to all of the routes:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill.scalalib._
+
+import $ivy.`com.lihaoyi::mill-contrib-playlib:$MILL_VERSION`, mill.playlib._
+
+object app extends ScalaModule with RouterModule {
+ def playVersion = &quot;2.7.0&quot;
+ override def routesAdditionalImport = Seq(&quot;my.additional.stuff._&quot;, &quot;my.other.stuff._&quot;)
+}
+</code></pre><h2 id="scalapb" class="Styles-hoverBox">ScalaPB<a href="#scalapb" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>This module allows <a href="https://scalapb.github.io">ScalaPB</a> to be used in Mill builds. ScalaPB is a <a href="https://developers.google.com/protocol-buffers/">Protocol Buffers</a> compiler plugin that generates Scala case classes, encoders and decoders for protobuf messages.</p>
+<p>To declare a module that uses ScalaPB you can extend the <code>mill.contrib.scalapblib.ScalaPBModule</code> trait when defining your module.</p>
+<p>This creates a Scala module which compiles <code>.proto</code> files in the <code>protobuf</code> folder of the module with ScalaPB and adds the resulting <code>.scala</code> sources to your module's <code>generatedSources</code>.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+
+import $ivy.`com.lihaoyi::mill-contrib-scalapblib:$MILL_VERSION`
+import contrib.scalapblib._
+
+object example extends ScalaPBModule {
+ def scalaVersion = &quot;2.12.6&quot;
+ def scalaPBVersion = &quot;0.7.4&quot;
+}
+</code></pre>
+<p>This defines a project with the following layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">build.sc
+example/
+ src/
+ protobuf/
+ resources/
+</code></pre><h3 id="configuration-options" class="Styles-hoverBox">Configuration options<a href="#configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li>
+ <p>scalaPBVersion (mandatory) - The ScalaPB version <code>String</code> e.g. <code>&quot;0.7.4&quot;</code></p></li>
+ <li>
+ <p>scalaPBFlatPackage - A <code>Boolean</code> option which determines whether the <code>.proto</code> file name should be appended as the final segment of the package name in the generated sources.</p></li>
+ <li>
+ <p>scalaPBJavaConversions - A <code>Boolean</code> option which determines whether methods for converting between the generated Scala classes and the Protocol Buffers Java API classes should be generated.</p></li>
+ <li>
+ <p>scalaPBGrpc - A <code>Boolean</code> option which determines whether <a href="https://grpc.io">grpc</a> stubs should be generated.</p></li>
+ <li>
+ <p>scalaPBSingleLineToProtoString - A <code>Boolean</code> option which determines whether the generated <code>.toString</code> methods should use a single line format.</p></li>
+</ul>
+<p>If you'd like to configure the options that are passed to the ScalaPB compiler directly, you can override the <code>scalaPBOptions</code> task, for example:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+
+import $ivy.`com.lihaoyi::mill-contrib-scalapblib:$MILL_VERSION`
+import contrib.scalapblib._
+
+object example extends ScalaPBModule {
+ def scalaVersion = &quot;2.12.6&quot;
+ def scalaPBVersion = &quot;0.7.4&quot;
+ override def scalaPBOptions = &quot;flat_package,java_conversions&quot;
+}
+</code></pre><h2 id="scoverage" class="Styles-hoverBox">Scoverage<a href="#scoverage" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>This module allows you to generate code coverage reports for Scala projects with <a href="https://github.com/scoverage">Scoverage</a> via the <a href="https://github.com/scoverage/scalac-scoverage-plugin">scalac-scoverage-plugin</a>.</p>
+<p>To declare a module for which you want to generate coverage reports you can extends the <code>mill.contrib.scoverage.ScoverageModule</code> trait when defining your module. Additionally, you must define a submodule that extends the <code>ScoverageTests</code> trait that belongs to your instance of <code>ScoverageModule</code>.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import $ivy.`com.lihaoyi::mill-contrib-scoverage:$MILL_VERSION`
+import mill.contrib.scoverage.ScoverageModule
+
+object foo extends ScoverageModule {
+ def scalaVersion = &quot;2.12.9&quot;
+ def scoverageVersion = &quot;1.4.0&quot;
+
+ object test extends ScoverageTests {
+ def ivyDeps = Agg(ivy&quot;org.scalatest::scalatest:3.0.8&quot;)
+ def testFrameworks = Seq(&quot;org.scalatest.tools.Framework&quot;)
+ }
+}
+</code></pre>
+<p>In addition to the normal tasks available to your Scala module, Scoverage modules introduce a few new tasks and changes the behavior of an existing one.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">mill foo.scoverage.compile # compiles your module with test instrumentation
+ # (you don&#39;t have to run this manually, running the test task will force its invocation)
+
+mill foo.test # tests your project and collects metrics on code coverage
+mill foo.scoverage.htmlReport # uses the metrics collected by a previous test run to generate a coverage report in html format
+mill foo.scoverage.xmlReport # uses the metrics collected by a previous test run to generate a coverage report in xml format
+</code></pre>
+<p>The measurement data is available at <code>out/foo/scoverage/data/</code>, the html report is saved in <code>out/foo/scoverage/htmlReport/</code>, and the xml report is saved in <code>out/foo/scoverage/xmlReport/</code>.</p><h2 id="testng" class="Styles-hoverBox">TestNG<a href="#testng" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Provides support for <a href="https://testng.org/doc/index.html">TestNG</a>.</p>
+<p>To use TestNG as test framework, you need to add it to the <code>TestModule.testFrameworks</code> property.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill.scalalib._
+
+object project extends ScalaModule {
+ object test extends Tests{
+ def testFrameworks = Seq(&quot;mill.testng.TestNGFramework&quot;)
+ }
+}
+</code></pre><h2 id="tut" class="Styles-hoverBox">Tut<a href="#tut" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>This module allows <a href="https://tpolecat.github.io/tut">Tut</a> to be used in Mill builds. Tut is a documentation tool which compiles and evaluates Scala code in documentation files and provides various options for configuring how the results will be displayed in the compiled documentation.</p>
+<p>To declare a module that uses Tut you can extend the <code>mill.contrib.tut.TutModule</code> trait when defining your module.</p>
+<p>This creates a Scala module which compiles markdown, HTML and <code>.txt</code> files in the <code>tut</code> folder of the module with Tut.</p>
+<p>By default the resulting documents are simply placed in the Mill build output folder but they can be placed elsewhere by overriding the <code>tutTargetDirectory</code> task.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+
+import $ivy.`com.lihaoyi::mill-contrib-tut:$MILL_VERSION`
+import contrib.tut._
+
+object example extends TutModule {
+ def scalaVersion = &quot;2.12.6&quot;
+ def tutVersion = &quot;0.6.7&quot;
+}
+</code></pre>
+<p>This defines a project with the following layout:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">build.sc
+example/
+ src/
+ tut/
+ resources/
+</code></pre>
+<p>In order to compile documentation we can execute the <code>tut</code> task in the module:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">sh&gt; mill example.tut
+</code></pre><h3 id="configuration-options" class="Styles-hoverBox">Configuration options<a href="#configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li>
+ <p>tutSourceDirectory - This task determines where documentation files must be placed in order to be compiled with Tut. By default this is the <code>tut</code> folder at the root of the module.</p></li>
+ <li>
+ <p>tutTargetDirectory - A task which determines where the compiled documentation files will be placed. By default this is simply the Mill build's output folder for the <code>tutTargetDirectory</code> task but this can be reconfigured so that documentation goes to the root of the module (e.g. <code>millSourcePath</code>) or to a dedicated folder (e.g. <code>millSourcePath / &#39;docs</code>)</p></li>
+ <li>
+ <p>tutClasspath - A task which determines what classpath is used when compiling documentation. By default this is configured to use the same inputs as the <code>runClasspath</code>, except for using <code>tutIvyDeps</code> rather than the module's <code>ivyDeps</code>.</p></li>
+ <li>
+ <p>tutScalacPluginIvyDeps - A task which determines the scalac plugins which will be used when compiling code examples with Tut. The default is to use the <code>scalacPluginIvyDeps</code> for the module.</p></li>
+ <li>
+ <p>tutNameFilter - A <code>scala.util.matching.Regex</code> task which will be used to determine which files should be compiled with tut. The default pattern is as follows: <code>.*\.(md|markdown|txt|htm|html)</code>.</p></li>
+ <li>
+ <p>tutScalacOptions - The scalac options which will be used when compiling code examples with Tut. The default is to use the <code>scalacOptions</code> for the module but filtering out options which are problematic in the REPL, e.g. <code>-Xfatal-warnings</code>, <code>-Ywarn-unused-imports</code>.</p></li>
+ <li>
+ <p>tutVersion - The version of Tut to use.</p></li>
+ <li>
+ <p>tutIvyDeps - A task which determines how to fetch the Tut jar file and all of the dependencies required to compile documentation for the module and returns the resulting files.</p></li>
+ <li>
+ <p>tutPluginJars - A task which performs the dependency resolution for the scalac plugins to be used with Tut.</p></li>
+</ul><h2 id="twirl" class="Styles-hoverBox">Twirl<a href="#twirl" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Twirl templates support.</p>
+<p>To declare a module that needs to compile twirl templates you must extend the <code>mill.twirllib.TwirlModule</code> trait when defining your module. Also note that twirl templates get compiled into scala code, so you also need to extend <code>ScalaModule</code>.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill.scalalib._
+
+import $ivy.`com.lihaoyi::mill-contrib-twirllib:$MILL_VERSION`, mill.twirllib._
+
+object app extends ScalaModule with TwirlModule {
+// ...
+}
+</code></pre><h3 id="twirl-configuration-options" class="Styles-hoverBox">Twirl configuration options<a href="#twirl-configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><code>def twirlVersion: T[String]</code> (mandatory) - the version of the twirl compiler to use, like "1.3.15"</li>
+ <li><code>def twirlAdditionalImports: Seq[String] = Nil</code> - the additional imports that will be added by twirl compiler to the top of all templates</li>
+ <li><code>def twirlConstructorAnnotations: Seq[String] = Nil</code> - annotations added to the generated classes' constructors (note it only applies to templates with <code>@this(...)</code> constructors)</li>
+ <li><code>def twirlCodec = Codec(Properties.sourceEncoding)</code> - the codec used to generate the files (the default is the same sbt plugin uses)</li>
+ <li><code>def twirlInclusiveDot: Boolean = false</code></li>
+</ul><h3 id="details" class="Styles-hoverBox">Details<a href="#details" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The following filesystem layout is expected:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">build.sc
+app/
+ views/
+ view1.scala.html
+ view2.scala.html
+</code></pre>
+<p><code>TwirlModule</code> adds the <code>compileTwirl</code> task to the module:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">mill app.compileTwirl
+</code></pre>
+<p>(it will be automatically run whenever you compile your module)</p>
+<p>This task will compile <code>*.scala.html</code> templates (and others, like <code>*.scala.txt</code>) into the <code>out/app/compileTwirl/dest</code> directory. This directory must be added to the generated sources of the module to be compiled and made accessible from the rest of the code:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill.scalalib._
+
+import $ivy.`com.lihaoyi::mill-contrib-twirllib:$MILL_VERSION`, mill.twirllib._
+
+object app extends ScalaModule with TwirlModule {
+ def twirlVersion = &quot;1.3.15&quot;
+ def generatedSources = T{ Seq(compileTwirl().classes) }
+}
+</code></pre>
+<p>To add additional imports to all of the twirl templates:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill.scalalib._
+
+import $ivy.`com.lihaoyi::mill-contrib-twirllib:$MILL_VERSION`, mill.twirllib._
+
+object app extends ScalaModule with TwirlModule {
+ def twirlVersion = &quot;1.3.15&quot;
+ override def twirlAdditionalImports = Seq(&quot;my.additional.stuff._&quot;, &quot;my.other.stuff._&quot;)
+ def generatedSources = T{ Seq(compileTwirl().classes) }
+}
+</code></pre>
+<p>as the result all templates will get this line at the top:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">@import &quot;my.additional.stuff._&quot;
+@import &quot;my.other.stuff._&quot;
+</code></pre>
+<p>Besides that, twirl compiler has default imports, at the moment these:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">Seq(
+ &quot;_root_.play.twirl.api.TwirlFeatureImports._&quot;,
+ &quot;_root_.play.twirl.api.TwirlHelperImports._&quot;,
+ &quot;_root_.play.twirl.api.Html&quot;,
+ &quot;_root_.play.twirl.api.JavaScript&quot;,
+ &quot;_root_.play.twirl.api.Txt&quot;,
+ &quot;_root_.play.twirl.api.Xml&quot;
+)
+</code></pre>
+<p>These imports will always be added to every template. You don't need to list them if you override <code>twirlAdditionalImports</code>.</p><h3 id="example" class="Styles-hoverBox">Example<a href="#example" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>There's an <a href="https://github.com/lihaoyi/cask/tree/master/example/twirl">example project</a></p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="mill-internals.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Mill Internals</a><a href="thirdparty-modules.html">Thirdparty Modules <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/cross-builds.html b/page/cross-builds.html
new file mode 100644
index 00000000..52e2cac3
--- /dev/null
+++ b/page/cross-builds.html
@@ -0,0 +1,220 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Cross Builds</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#defining-cross-modules">Defining Cross Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-cross-modules-from-outside">Using Cross Modules from Outside</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-cross-modules-from-other-cross-modules">Using Cross Modules from other Cross Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#cross-resolvers">Cross Resolvers</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Cross Builds</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="modules.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Modules</a><a href="extending-mill.html">Extending Mill <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>Mill handles cross-building of all sorts via the <code>Cross[T]</code> module.</p><h2 id="defining-cross-modules" class="Styles-hoverBox">Defining Cross Modules<a href="#defining-cross-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>You can use this as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Cross[FooModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class FooModule(crossVersion: String) extends Module {
+ def suffix = T { crossVersion }
+ def bigSuffix = T { suffix().toUpperCase() }
+}
+</code></pre>
+<p>This defines three copies of <code>FooModule</code>: <code>&quot;210&quot;</code>, <code>&quot;211&quot;</code> and <code>&quot;212&quot;</code>, each of which has their own <code>suffix</code> target. You can then run them via</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill show foo[2.10].suffix
+mill show foo[2.10].bigSuffix
+mill show foo[2.11].suffix
+mill show foo[2.11].bigSuffix
+mill show foo[2.12].suffix
+mill show foo[2.12].bigSuffix
+</code></pre>
+<p>The modules each also have a <code>millSourcePath</code> of</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">foo/2.10
+foo/2.11
+foo/2.12
+</code></pre>
+<p>And the <code>suffix</code> targets will have the corresponding output paths for their metadata and files:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">foo/2.10/suffix
+foo/2.10/bigSuffix
+foo/2.11/suffix
+foo/2.11/bigSuffix
+foo/2.12/suffix
+foo/2.12/bigSuffix
+</code></pre>
+<p>You can also have a cross-build with multiple inputs:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">val crossMatrix = for {
+ crossVersion &lt;- Seq(&quot;210&quot;, &quot;211&quot;, &quot;212&quot;)
+ platform &lt;- Seq(&quot;jvm&quot;, &quot;js&quot;, &quot;native&quot;)
+ if !(platform == &quot;native&quot; &amp;&amp; crossVersion != &quot;212&quot;)
+} yield (crossVersion, platform)
+
+object foo extends mill.Cross[FooModule](crossMatrix:_*)
+class FooModule(crossVersion: String, platform: String) extends Module {
+ def suffix = T { crossVersion + &quot;_&quot; + platform }
+}
+</code></pre>
+<p>Here, we define our cross-values programmatically using a <code>for</code>-loop that spits out tuples instead of individual values. Our <code>FooModule</code> template class then takes two parameters instead of one. This creates the following modules each with their own <code>suffix</code> target:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill show foo[210,jvm].suffix
+mill show foo[211,jvm].suffix
+mill show foo[212,jvm].suffix
+mill show foo[210,js].suffix
+mill show foo[211,js].suffix
+mill show foo[212,js].suffix
+mill show foo[212,native].suffix
+</code></pre><h2 id="using-cross-modules-from-outside" class="Styles-hoverBox">Using Cross Modules from Outside<a href="#using-cross-modules-from-outside" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>You can refer to targets defined in cross-modules as follows:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Cross[FooModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class FooModule(crossVersion: String) extends Module {
+ def suffix = T { crossVersion }
+}
+
+def bar = T { &quot;hello &quot; + foo(&quot;2.10&quot;).suffix }
+</code></pre>
+<p>Here, <code>foo(&quot;2.10&quot;)</code> references the <code>&quot;2.10&quot;</code> instance of <code>FooModule</code>. You can refer to whatever versions of the cross-module you want, even using multiple versions of the cross-module in the same target:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Cross[FooModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class FooModule(crossVersion: String) extends Module {
+ def suffix = T { crossVersion }
+}
+
+def bar = T { &quot;hello &quot; + foo(&quot;2.10&quot;).suffix + &quot; world &quot; + foo(&quot;2.12&quot;).suffix }
+</code></pre><h2 id="using-cross-modules-from-other-cross-modules" class="Styles-hoverBox">Using Cross Modules from other Cross Modules<a href="#using-cross-modules-from-other-cross-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Targets in cross-modules can depend on one another the same way that external targets:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Cross[FooModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class FooModule(crossVersion: String) extends Module {
+ def suffix = T { crossVersion }
+}
+
+object bar extends mill.Cross[BarModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class BarModule(crossVersion: String) extends Module {
+ def bigSuffix = T { foo(crossVersion).suffix().toUpperCase() }
+}
+</code></pre>
+<p>Here, you can run:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill show foo[2.10].suffix
+mill show foo[2.11].suffix
+mill show foo[2.12].suffix
+mill show bar[2.10].bigSuffix
+mill show bar[2.11].bigSuffix
+mill show bar[2.12].bigSuffix
+</code></pre><h2 id="cross-resolvers" class="Styles-hoverBox">Cross Resolvers<a href="#cross-resolvers" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>You can define an implicit <code>mill.define.Cross.Resolver</code> within your cross-modules, which would let you use a shorthand <code>foo()</code> syntax when referring to other cross-modules with an identical set of cross values:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">trait MyModule extends Module {
+ def crossVersion: String
+ implicit object resolver extends mill.define.Cross.Resolver[MyModule] {
+ def resolve[V &lt;: MyModule](c: Cross[V]): V = c.itemMap(List(crossVersion))
+ }
+}
+
+object foo extends mill.Cross[FooModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class FooModule(val crossVersion: String) extends MyModule {
+ def suffix = T { crossVersion }
+}
+
+object bar extends mill.Cross[BarModule](&quot;2.10&quot;, &quot;2.11&quot;, &quot;2.12&quot;)
+class BarModule(val crossVersion: String) extends MyModule {
+ def longSuffix = T { &quot;_&quot; + foo().suffix() }
+}
+</code></pre>
+<p>While the example <code>resolver</code> simply looks up the target <code>Cross</code> value for the cross-module instance with the same <code>crossVersion</code>, you can make the resolver arbitrarily complex. E.g. the <code>resolver</code> for <code>mill.scalalib.CrossSbtModule</code> looks for a cross-module instance whose <code>scalaVersion</code> is binary compatible (e.g. 2.10.5 is compatible with 2.10.3) with the current cross-module.</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="modules.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Modules</a><a href="extending-mill.html">Extending Mill <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/extending-mill.html b/page/extending-mill.html
new file mode 100644
index 00000000..f6c7d0e7
--- /dev/null
+++ b/page/extending-mill.html
@@ -0,0 +1,210 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Extending Mill</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#custom-targets--commands">Custom Targets &amp; Commands</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#compile-some-javascript-with-webpack-and-put-it-in-your-runtime-classpath">Compile some Javascript with Webpack and put it in your runtime classpath:</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#deploy-your-compiled-assembly-to-aws">Deploy your compiled assembly to AWS</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#custom-workers">Custom Workers</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#custom-modules">Custom Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#import-file">import $file</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#import-ivy">import $ivy</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#evaluator-commands-experimental">Evaluator Commands (experimental)</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Extending Mill</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="cross-builds.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Cross Builds</a><a href="mill-internals.html">Mill Internals <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>There are many different ways of extending Mill, depending on how much customization and flexibility you need. This page will go through your options from the easiest/least-flexible to the hardest/most-flexible.</p><h2 id="custom-targets--commands" class="Styles-hoverBox">Custom Targets &amp; Commands<a href="#custom-targets--commands" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The simplest way of adding custom functionality to Mill is to define a custom Target or Command:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def foo = T { ... }
+def bar(x: Int, s: String) = T.command { ... }
+</code></pre>
+<p>These can depend on other Targets, contain arbitrary code, and be placed top-level or within any module. If you have something you just want to <em>do</em> that isn't covered by the built-in <code>ScalaModule</code>s/<code>ScalaJSModule</code>s, simply write a custom Target (for cached computations) or Command (for un-cached actions) and you're done.</p>
+<p>For subprocess/filesystem operations, you can use the <a href="http://ammonite.io/#Ammonite-Ops">Ammonite-Ops</a> library that comes bundled with Mill, or even plain <code>java.nio</code>/<code>java.lang.Process</code>. Each target gets its own <a href="http://www.lihaoyi.com/mill/page/tasks#millutilctxdestctx">T.ctx().dest</a> folder that you can use to place files without worrying about colliding with other targets.</p>
+<p>This covers use cases like:</p><h3 id="compile-some-javascript-with-webpack-and-put-it-in-your-runtime-classpath" class="Styles-hoverBox">Compile some Javascript with Webpack and put it in your runtime classpath:<a href="#compile-some-javascript-with-webpack-and-put-it-in-your-runtime-classpath" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def doWebpackStuff(sources: Seq[PathRef]): PathRef = ???
+
+def javascriptSources = T.sources { millSourcePath / &quot;js&quot; }
+def compiledJavascript = T { doWebpackStuff(javascriptSources()) }
+object foo extends ScalaModule {
+ def runClasspath = T { super.runClasspath() ++ compiledJavascript() }
+}
+</code></pre><h3 id="deploy-your-compiled-assembly-to-aws" class="Styles-hoverBox">Deploy your compiled assembly to AWS<a href="#deploy-your-compiled-assembly-to-aws" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends ScalaModule {
+
+}
+
+def deploy(assembly: PathRef, credentials: String) = ???
+
+def deployFoo(credentials: String) = T.command { deployFoo(foo.assembly()) }
+</code></pre><h2 id="custom-workers" class="Styles-hoverBox">Custom Workers<a href="#custom-workers" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p><a href="#custom-targets--commands">Custom Targets &amp; Commands</a> are re-computed from scratch each time; sometimes you want to keep values around in-memory when using <code>--watch</code> or the Build REPL. E.g. you may want to keep a webpack process running so webpack's own internal caches are hot and compilation is fast:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def webpackWorker = T.worker {
+ // Spawn a process using java.lang.Process and return it
+}
+
+def javascriptSources = T.sources { millSourcePath / &quot;js&quot; }
+
+def doWebpackStuff(webpackProcess: Process, sources: Seq[PathRef]): PathRef = ???
+
+def compiledJavascript = T { doWebpackStuff(webpackWorker(), javascriptSources()) }
+</code></pre>
+<p>Mill itself uses <code>T.worker</code>s for its built-in Scala support: we keep the Scala compiler in memory between compilations, rather than discarding it each time, in order to improve performance.</p><h2 id="custom-modules" class="Styles-hoverBox">Custom Modules<a href="#custom-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">trait FooModule extends mill.Module {
+ def bar = T { &quot;hello&quot; }
+ def baz = T { &quot;world&quot; }
+}
+</code></pre>
+<p>Custom modules are useful if you have a common set of tasks that you want to re-used across different parts of your build. You simply define a <code>trait</code> inheriting from <code>mill.Module</code>, and then use that <code>trait</code> as many times as you want in various <code>object</code>s:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo1 extends FooModule
+object foo2 extends FooModule {
+ def qux = T { &quot;I am Cow&quot; }
+}
+</code></pre>
+<p>You can also define a <code>trait</code> extending the built-in <code>ScalaModule</code> if you have common configuration you want to apply to all your <code>ScalaModule</code>s:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">trait FooModule extends ScalaModule {
+ def scalaVersion = &quot;2.11.11&quot;
+ object test extends Tests {
+ def ivyDeps = Agg(ivy&quot;org.scalatest::scalatest:3.0.4&quot;)
+ def testFrameworks = Seq(&quot;org.scalatest.tools.Framework&quot;)
+ }
+}
+</code></pre><h2 id="import-file" class="Styles-hoverBox">import $file<a href="#import-file" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>If you want to define some functionality that can be used both inside and outside the build, you can create a new <code>foo.sc</code> file next to your <code>build.sc</code>, <code>import $file.foo</code>, and use it in your <code>build.sc</code> file:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// foo.sc
+def fooValue() = 31337
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import $file.foo
+def printFoo() = T.command { println(foo.fooValue()) }
+</code></pre>
+<p>Mill's <code>import $file</code> syntax supports the full functionality of <a href="http://ammonite.io/#ScalaScripts">Ammonite Scripts</a></p><h2 id="import-ivy" class="Styles-hoverBox">import $ivy<a href="#import-ivy" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>If you want to pull in artifacts from the public repositories (e.g. Maven Central) for use in your build, you can simply use <code>import $ivy</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import $ivy.`com.lihaoyi::scalatags:0.6.2`
+
+def generatedHtml = T {
+ import scalatags.Text.all._
+ html(
+ head(),
+ body(
+ h1(&quot;Hello&quot;),
+ p(&quot;World&quot;)
+ )
+ ).render
+}
+</code></pre>
+<p>This creates the <code>generatedHtml</code> target which can then be used however you would like: written to a file, further processed, etc.</p>
+<p>If you want to publish re-usable libraries that <em>other</em> people can use in their builds, simply publish your code as a library to maven central.</p>
+<p>For more information, see Ammonite's <a href="http://ammonite.io/#import$ivy">Ivy Dependencies documentation</a>.</p><h2 id="evaluator-commands-experimental" class="Styles-hoverBox">Evaluator Commands (experimental)<a href="#evaluator-commands-experimental" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p><em>Evaluator Command are experimental and suspected to change. See <a href="https://github.com/lihaoyi/mill/issues/502">issue #502</a> for details.</em></p>
+<p>You can define a command that takes in the current <code>Evaluator</code> as an argument, which you can use to inspect the entire build, or run arbitrary tasks. For example, here is the <code>mill.scalalib.GenIdea/idea</code> command which uses this to traverse the module-tree and generate an Intellij project config for your build.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def idea(ev: Evaluator) = T.command {
+ mill.scalalib.GenIdea(
+ implicitly,
+ ev.rootModule,
+ ev.discover
+ )
+}
+</code></pre>
+<p>Many built-in tools are implemented as custom evaluator commands: <a href="http://www.lihaoyi.com/mill/#all">all</a>, <a href="http://www.lihaoyi.com/mill/#inspect">inspect</a>, <a href="http://www.lihaoyi.com/mill/#resolve">resolve</a>, <a href="http://www.lihaoyi.com/mill/#show">show</a>. If you want a way to run Mill commands and programmatically manipulate the tasks and outputs, you do so with your own evaluator command.</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="cross-builds.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Cross Builds</a><a href="mill-internals.html">Mill Internals <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/mill-internals.html b/page/mill-internals.html
new file mode 100644
index 00000000..acaccbf9
--- /dev/null
+++ b/page/mill-internals.html
@@ -0,0 +1,264 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Mill Internals</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#mill-design-principles">Mill Design Principles</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#dependency-graph-first">Dependency graph first</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#builds-are-hierarchical">Builds are hierarchical</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#caching-by-default">Caching by default</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#short-lived-build-processes">Short-lived build processes</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#static-dependency-graph-and-applicative-tasks">Static dependency graph and Applicative tasks</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#how-mill-aims-for-simple">How Mill aims for Simple</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#the-object-hierarchy">The Object Hierarchy</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#the-call-graph">The Call Graph</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#instantiating-traits--classes">Instantiating Traits &amp; Classes</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#prior-work">Prior Work</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#sbt">SBT</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#bazel">Bazel</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#scalarx">Scala.Rx</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#cbt">CBT</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Mill Internals</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="extending-mill.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Extending Mill</a><a href="contrib-modules.html">Contrib Modules <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><h2 id="mill-design-principles" class="Styles-hoverBox">Mill Design Principles<a href="#mill-design-principles" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>A lot of Mill's design principles are intended to fix SBT's flaws, as described in the blog post <a href="http://www.lihaoyi.com/post/SowhatswrongwithSBT.html">What's wrong with SBT</a>, building on the best ideas from tools like <a href="https://github.com/cvogt/cbt">CBT</a> and <a href="https://bazel.build/">Bazel</a>, and the ideas from my blog post <a href="http://www.lihaoyi.com/post/BuildToolsasPureFunctionalPrograms.html">Build Tools as Pure Functional Programs</a>. Before working on Mill, read through that post to understand where it is coming from!</p><h3 id="dependency-graph-first" class="Styles-hoverBox">Dependency graph first<a href="#dependency-graph-first" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Mill's most important abstraction is the dependency graph of <code>Task</code>s. Constructed using the <code>T {...}</code> <code>T.task {...}</code> <code>T.command {...}</code> syntax, these track the dependencies between steps of a build, so those steps can be executed in the correct order, queried, or parallelized.</p>
+<p>While Mill provides helpers like <code>ScalaModule</code> and other things you can use to quickly instantiate a bunch of related tasks (resolve dependencies, find sources, compile, package into jar, ...) these are secondary. When Mill executes, the dependency graph is what matters: any other mode of organization (hierarchies, modules, inheritance, etc.) is only important to create this dependency graph of <code>Task</code>s.</p><h3 id="builds-are-hierarchical" class="Styles-hoverBox">Builds are hierarchical<a href="#builds-are-hierarchical" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The syntax for running targets from the command line <code>mill Foo.bar.baz</code> is the same as referencing a target in Scala code, <code>Foo.bar.baz</code></p>
+<p>Everything that you can run from the command line lives in an object hierarchy in your <code>build.sc</code> file. Different parts of the hierarchy can have different <code>Target</code>s available: just add a new <code>def foo = T {...}</code> somewhere and you'll be able to run it.</p>
+<p>Cross builds, using the <code>Cross</code> data structure, are just another kind of node in the object hierarchy. The only difference is syntax: from the command line you'd run something via <code>mill core.cross[a].printIt</code> while from code you use <code>core.cross(&quot;a&quot;).printIt</code> due to different restrictions in Scala/Bash syntax.</p><h3 id="caching-by-default" class="Styles-hoverBox">Caching by default<a href="#caching-by-default" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Every <code>Target</code> in a build, defined by <code>def foo = T {...}</code>, is cached by default. Currently this is done using a <code>foo/meta.json</code> file in the <code>out/</code> folder. The <code>Target</code> is also provided a <code>foo/</code> path on the filesystem dedicated to it, for it to store output files etc.</p>
+<p>This happens whether you want it to or not. Every <code>Target</code> is cached, not just the "slow" ones like <code>compile</code> or <code>assembly</code>.</p>
+<p>Caching is keyed on the <code>.hashCode</code> of the returned value. For <code>Target</code>s returning the contents of a file/folder on disk, they return <code>PathRef</code> instances whose hashcode is based on the hash of the disk contents. Serialization of the returned values is tentatively done using uPickle.</p><h3 id="short-lived-build-processes" class="Styles-hoverBox">Short-lived build processes<a href="#short-lived-build-processes" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The Mill build process is meant to be run over and over, not only as a long-lived daemon/console. That means we must minimize the startup time of the process, and that a new process must be able to re-construct the in-memory data structures where a previous process left off, in order to continue the build.</p>
+<p>Re-construction is done via the hierarchical nature of the build: each <code>Target</code> <code>foo.bar.baz</code> has a fixed position in the build hierarchy, and thus a fixed position on disk <code>out/foo/bar/baz/meta.json</code>. When the old process dies and a new process starts, there will be a new instance of <code>Target</code> with the same implementation code and same position in the build hierarchy: this new <code>Target</code> can then load the <code>out/foo/bar/baz/meta.json</code> file and pick up where the previous process left off.</p>
+<p>Minimizing startup time means aggressive caching, as well as minimizing the total amount of bytecode used: Mill's current 1-2s startup time is dominated by JVM classloading. In future, we may have a long lived console or nailgun/drip-based server/client models to speed up interactive usage, but we should always keep "cold" startup as fast as possible.</p><h3 id="static-dependency-graph-and-applicative-tasks" class="Styles-hoverBox">Static dependency graph and Applicative tasks<a href="#static-dependency-graph-and-applicative-tasks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p><code>Task</code>s are <em>Applicative</em>, not <em>Monadic</em>. There is <code>.map</code>, <code>.zip</code>, but no <code>.flatMap</code> operation. That means that we can know the structure of the entire dependency graph before we start executing <code>Task</code>s. This lets us perform all sorts of useful operations on the graph before running it:</p>
+<ul>
+ <li>
+ <p>Given a Target the user wants to run, pre-compute and display what targets will be evaluated ("dry run"), without running them</p></li>
+ <li>
+ <p>Automatically parallelize different parts of the dependency graph that do not depend on each other, perhaps even distributing it to different worker machines like Bazel/Pants can</p></li>
+ <li>
+ <p>Visualize the dependency graph easily, e.g. by dumping to a DOT file</p></li>
+ <li>
+ <p>Query the graph, e.g. "why does this thing depend on that other thing?"</p></li>
+ <li>
+ <p>Avoid running tasks "halfway": if a Target's upstream Targets fail, we can skip the Target completely rather than running halfway and then bailing out with an exception</p></li>
+</ul>
+<p>In order to avoid making people using <code>.map</code> and <code>.zip</code> all over the place when defining their <code>Task</code>s, we use the <code>T {...}</code>/<code>T.task {...}</code>/<code>T.command {...}</code> macros which allow you to use <code>Task#apply()</code> within the block to "extract" a value.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def test() = T.command {
+ TestRunner.apply(
+ &quot;mill.UTestFramework&quot;,
+ runDepClasspath().map(_.path) :+ compile().path,
+ Seq(compile().path)
+
+}
+</code></pre>
+<p>This is roughly equivalent to the following:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def test() = T.command { T.zipMap(runDepClasspath, compile, compile) {
+ (runDepClasspath1, compile2, compile3) =&gt;
+ TestRunner.apply(
+ &quot;mill.UTestFramework&quot;,
+ runDepClasspath1.map(_.path) :+ compile2.path,
+ Seq(compile3.path)
+ )
+}
+</code></pre>
+<p>This is similar to SBT's <code>:=</code>/<code>.value</code> macros, or <code>scala-async</code>'s <code>async</code>/<code>await</code>. Like those, the <code>T {...}</code> macro should let users program most of their code in a "direct" style and have it "automatically" lifted into a graph of <code>Task</code>s.</p><h2 id="how-mill-aims-for-simple" class="Styles-hoverBox">How Mill aims for Simple<a href="#how-mill-aims-for-simple" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Why should you expect that the Mill build tool can achieve simple, easy &amp; flexible, where other build tools in the past have failed?</p>
+<p>Build tools inherently encompass a huge number of different concepts:</p>
+<ul>
+ <li>What "Tasks" depends on what?</li>
+ <li>How do I define my own tasks?</li>
+ <li>Where do source files come from?</li>
+ <li>What needs to run in what order to do what I want?</li>
+ <li>What can be parallelized and what can't?</li>
+ <li>How do tasks pass data to each other? What data do they pass?</li>
+ <li>What tasks are cached? Where?</li>
+ <li>How are tasks run from the command line?</li>
+ <li>How do you deal with the repetition inherent in a build? (e.g. compile, run &amp; test tasks for every "module")</li>
+ <li>What is a "Module"? How do they relate to "Tasks"?</li>
+ <li>How do you configure a Module to do something different?</li>
+ <li>How are cross-builds (across different configurations) handled?</li>
+</ul>
+<p>These are a lot of questions to answer, and we haven't even started talking about the actually compiling/running any code yet! If each such facet of a build was modelled separately, it's easy to have an explosion of different concepts that would make a build tool hard to understand.</p>
+<p>Before you continue, take a moment to think: how would you answer to each of those questions using an existing build tool you are familiar with? Different tools like <a href="http://www.scala-sbt.org/">SBT</a>, <a href="https://fake.build/legacy-index.html">Fake</a>, <a href="https://gradle.org/">Gradle</a> or <a href="https://gruntjs.com/">Grunt</a> have very different answers.</p>
+<p>Mill aims to provide the answer to these questions using as few, as familiar core concepts as possible. The entire Mill build is oriented around a few concepts:</p>
+<ul>
+ <li>The Object Hierarchy</li>
+ <li>The Call Graph</li>
+ <li>Instantiating Traits &amp; Classes</li>
+</ul>
+<p>These concepts are already familiar to anyone experienced in Scala (or any other programming language...), but are enough to answer all of the complicated build-related questions listed above.</p><h2 id="the-object-hierarchy" class="Styles-hoverBox">The Object Hierarchy<a href="#the-object-hierarchy" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The module hierarchy is the graph of objects, starting from the root of the <code>build.sc</code> file, that extend <code>mill.Module</code>. At the leaves of the hierarchy are the <code>Target</code>s you can run.</p>
+<p>A <code>Target</code>'s position in the module hierarchy tells you many things. For example, a <code>Target</code> at position <code>core.test.compile</code> would:</p>
+<ul>
+ <li>
+ <p>Cache output metadata at <code>out/core/test/compile/meta.json</code></p></li>
+ <li>
+ <p>Output files to the folder <code>out/core/test/compile/dest/</code></p></li>
+ <li>
+ <p>Source files default to a folder in <code>core/test/</code>, <code>core/test/src/</code></p></li>
+ <li>
+ <p>Be runnable from the command-line via <code>mill core.test.compile</code></p></li>
+ <li>
+ <p>Be referenced programmatically (from other <code>Target</code>s) via <code>core.test.compile</code></p></li>
+</ul>
+<p>From the position of any <code>Target</code> within the object hierarchy, you immediately know how to run it, find its output files, find any caches, or refer to it from other <code>Target</code>s. You know up-front where the <code>Target</code>'s data "lives" on disk, and are sure that it will never clash with any other <code>Target</code>'s data.</p><h2 id="the-call-graph" class="Styles-hoverBox">The Call Graph<a href="#the-call-graph" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The Scala call graph of "which target references which other target" is core to how Mill operates. This graph is reified via the <code>T {...}</code> macro to make it available to the Mill execution engine at runtime. The call graph tells you:</p>
+<ul>
+ <li>
+ <p>Which <code>Target</code>s depend on which other <code>Target</code>s</p></li>
+ <li>
+ <p>For a given <code>Target</code> to be built, what other <code>Target</code>s need to be run and in what order</p></li>
+ <li>
+ <p>Which <code>Target</code>s can be evaluated in parallel</p></li>
+ <li>
+ <p>What source files need to be watched when using <code>--watch</code> on a given target (by tracing the call graph up to the <code>Source</code>s)</p></li>
+ <li>
+ <p>What a given <code>Target</code> makes available for other <code>Target</code>s to depend on (via its return value)</p></li>
+ <li>
+ <p>Defining your own task that depends on others is as simple as <code>def foo =
+ T {...}</code></p></li>
+</ul>
+<p>The call graph within your Scala code is essentially a data-flow graph: by defining a snippet of code:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">val b = ...
+val c = ...
+val d = ...
+val a = f(b, c, d)
+</code></pre>
+<p>you are telling everyone that the value <code>a</code> depends on the values of <code>b</code> <code>c</code> and <code>d</code>, processed by <code>f</code>. A build tool needs exactly the same data structure: knowing what <code>Target</code> depends on what other <code>Target</code>s, and what processing it does on its inputs!</p>
+<p>With Mill, you can take the Scala call graph, wrap everything in the <code>T {...}</code> macro, and get a <code>Target</code>-dependency graph that matches exactly the call-graph you already had:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">val b = T { ... }
+val c = T { ... }
+val d = T { ... }
+val a = T { f(b(), c(), d()) }
+</code></pre>
+<p>Thus, if you are familiar with how data flows through a normal Scala program, you already know how data flows through a Mill build! The Mill build evaluation may be incremental, it may cache things, it may read and write from disk, but the fundamental syntax, and the data-flow that syntax represents, is unchanged from your normal Scala code.</p><h2 id="instantiating-traits--classes" class="Styles-hoverBox">Instantiating Traits &amp; Classes<a href="#instantiating-traits--classes" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Classes and traits are a common way of re-using common data structures in Scala: if you have a bunch of fields which are related and you want to make multiple copies of those fields, you put them in a class/trait and instantiate it over and over.</p>
+<p>In Mill, inheriting from traits is the primary way for re-using common parts of a build:</p>
+<ul>
+ <li>
+ <p>Scala "project"s with multiple related <code>Target</code>s within them, are just a <code>Trait</code> you instantiate</p></li>
+ <li>
+ <p>Replacing the default <code>Target</code>s within a project, making them do new things or depend on new <code>Target</code>s, is simply <code>override</code>-ing them during inheritance</p></li>
+ <li>
+ <p>Modifying the default <code>Target</code>s within a project, making use of the old value to compute the new value, is simply <code>override</code>ing them and using <code>super.foo()</code></p></li>
+ <li>
+ <p>Required configuration parameters within a <code>project</code> are <code>abstract</code> members</p></li>
+ <li>
+ <p>Cross-builds are modelled as instantiating a (possibly anonymous) class multiple times, each instance with its own distinct set of <code>Target</code>s</p></li>
+</ul>
+<p>In normal Scala, you bundle up common fields &amp; functionality into a <code>class</code> you can instantiate over and over, and you can override the things you want to customize. Similarly, in Mill, you bundle up common parts of a build into <code>trait</code>s you can instantiate over and over, and you can override the things you want to customize. "Subprojects", "cross-builds", and many other concepts are reduced to simply instantiating a <code>trait</code> over and over, with tweaks.</p><h2 id="prior-work" class="Styles-hoverBox">Prior Work<a href="#prior-work" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2><h3 id="sbt" class="Styles-hoverBox">SBT<a href="#sbt" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Mill is built as a substitute for SBT, whose problems are <a href="http://www.lihaoyi.com/post/SowhatswrongwithSBT.html">described here</a>. Nevertheless, Mill takes on some parts of SBT (builds written in Scala, Task graph with an Applicative "idiom bracket" macro) where it makes sense.</p><h3 id="bazel" class="Styles-hoverBox">Bazel<a href="#bazel" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Mill is largely inspired by <a href="https://bazel.build/">Bazel</a>. In particular, the single-build-hierarchy, where every Target has an on-disk-cache/output-folder according to their position in the hierarchy, comes from Bazel.</p>
+<p>Bazel is a bit odd in its own right. The underlying data model is good (hierarchy + cached dependency graph) but getting there is hell. It (like SBT) is also a 3-layer interpretation model, but layers 1 &amp; 2 are almost exactly the same: mutable python which performs global side effects (layer 3 is the same dependency-graph evaluator as SBT/mill).</p>
+<p>You end up having to deal with a non-trivial python codebase where everything happens via:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="python">do_something(name=&quot;blah&quot;)
+</code></pre>
+<p>or</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="python">do_other_thing(dependencies=[&quot;blah&quot;])
+
+</code></pre>
+<p>where <code>&quot;blah&quot;</code> is a global identifier that is often constructed programmatically via string concatenation and passed around. This is quite challenging.</p>
+<p>Having the two layers be “just python” is great since people know python, but I think unnecessary two have two layers ("evaluating macros" and "evaluating rule impls") that are almost exactly the same, and I think making them interact via return values rather than via a global namespace of programmatically-constructed strings would make it easier to follow.</p>
+<p>With Mill, I’m trying to collapse Bazel’s Python layer 1 &amp; 2 into just 1 layer of Scala, and have it define its dependency graph/hierarchy by returning values, rather than by calling global-side-effecting APIs. I've had trouble trying to teach people how-to-bazel at work, and am pretty sure we can make something that's easier to use.</p><h3 id="scalarx" class="Styles-hoverBox">Scala.Rx<a href="#scalarx" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Mill's "direct-style" applicative syntax is inspired by my old <a href="https://github.com/lihaoyi/scala.rx">Scala.Rx</a> project. While there are differences (Mill captures the dependency graph lexically using Macros, Scala.Rx captures it at runtime), they are pretty similar.</p>
+<p>The end-goal is the same: to write code in a "direct style" and have it automatically "lifted" into a dependency graph, which you can introspect and use for incremental updates at runtime.</p>
+<p>Scala.Rx is itself build upon the 2010 paper <a href="https://infoscience.epfl.ch/record/148043/files/DeprecatingObserversTR2010.pdf">Deprecating the Observer Pattern</a>.</p><h3 id="cbt" class="Styles-hoverBox">CBT<a href="#cbt" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Mill looks a lot like <a href="https://github.com/cvogt/cbt">CBT</a>. The inheritance based model for customizing <code>Module</code>s/<code>ScalaModule</code>s comes straight from there, as does the "command line path matches Scala selector path" idea. Most other things are different though: the reified dependency graph, the execution model, the caching module all follow Bazel more than they do CBT</p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="extending-mill.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Extending Mill</a><a href="contrib-modules.html">Contrib Modules <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/modules.html b/page/modules.html
new file mode 100644
index 00000000..e708f9b6
--- /dev/null
+++ b/page/modules.html
@@ -0,0 +1,221 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Modules</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#using-modules">Using Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#overriding-targets">Overriding Targets</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#millsourcepath">millSourcePath</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#external-modules">External Modules</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#foreign-modules">Foreign Modules</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Modules</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="tasks.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tasks</a><a href="cross-builds.html">Cross Builds <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>Mill modules are <code>object</code>s extending <code>mill.Module</code>, and let you group related tasks together to keep things neat and organized. Mill's comes with built in modules such as <code>mill.scalalib.ScalaModule</code> and <code>mill.scalalib.CrossSbtModule</code>, but you can use modules for other purposes as well.</p><h2 id="using-modules" class="Styles-hoverBox">Using Modules<a href="#using-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The path to a Mill module from the root of your build file corresponds to the path you would use to run tasks within that module from the command line. e.g. for the following build:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Module {
+ def bar = T { &quot;hello&quot; }
+ object baz extends mill.Module {
+ def qux = T { &quot;world&quot; }
+ }
+}
+</code></pre>
+<p>You would be able to run the two targets via <code>mill foo.bar</code> or <code>mill
+foo.baz.qux</code>. You can use <code>mill show foo.bar</code> or <code>mill show foo.baz.qux</code> to make Mill echo out the string value being returned by each Target. The two targets will store their output metadata &amp; files at <code>./out/foo/bar</code> and <code>./out/foo/baz/qux</code> respectively.</p>
+<p>Modules also provide a way to define and re-use common collections of tasks, via Scala <code>trait</code>s. For example, you can define your own <code>FooModule</code> trait:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">trait FooModule extends mill.Module {
+ def bar = T { &quot;hello&quot; }
+ def baz = T { &quot;world&quot; }
+}
+</code></pre>
+<p>And use it to define multiple modules with the same <code>bar</code> and <code>baz</code> targets, along with any other customizations such as <code>qux</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo1 extends FooModule
+object foo2 extends FooModule {
+ def qux = T { &quot;I am Cow&quot; }
+}
+</code></pre>
+<p>This would make the following targets available from the command line</p>
+<ul>
+ <li><code>mill show foo1.bar</code></li>
+ <li><code>mill show foo1.baz</code></li>
+ <li><code>mill show foo2.bar</code></li>
+ <li><code>mill show foo2.baz</code></li>
+ <li><code>mill show foo2.qux</code></li>
+</ul>
+<p>The built-in <code>mill.scalalib</code> package uses this to define <code>mill.scalalib.ScalaModule</code>, <code>mill.scalalib.SbtModule</code> and <code>mill.scalalib.TestScalaModule</code>, all of which contain a set of "standard" operations such as <code>compile</code> <code>jar</code> or <code>assembly</code> that you may expect from a typical Scala module.</p>
+<p>When defining your own module abstractions, in general you should use <code>trait</code>s and not <code>class</code>es, except in the case of <a href="http://www.lihaoyi.com/mill/page/cross-builds.html">Cross Builds</a>.</p><h2 id="overriding-targets" class="Styles-hoverBox">Overriding Targets<a href="#overriding-targets" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">trait BaseModule extends Module {
+ def foo = T { Seq(&quot;base&quot;) }
+ def cmd(i: Int) = T.command { Seq(&quot;base&quot; + i) }
+}
+
+object canOverrideSuper with BaseModule {
+ def foo = T { super.foo() ++ Seq(&quot;object&quot;) }
+ def cmd(i: Int) = T.command { super.cmd(i)() ++ Seq(&quot;object&quot; + i) }
+}
+</code></pre>
+<p>You can override targets and commands to customize them or change what they do. The overriden version is available via <code>super</code>. You can omit the <code>override</code> keyword in Mill builds.</p><h2 id="millsourcepath" class="Styles-hoverBox">millSourcePath<a href="#millsourcepath" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Each Module has a <code>millSourcePath</code> field that corresponds to the path that module expects its input files to be on disk. Re-visiting our examples above:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Module {
+ def bar = T { &quot;hello&quot; }
+ object baz extends mill.Module {
+ def qux = T { &quot;world&quot; }
+ }
+}
+</code></pre>
+<p>The <code>foo</code> module has a <code>millSourcePath</code> of <code>./foo</code>, while the <code>foo.baz</code> module has a <code>millSourcePath</code> of <code>./foo/baz</code>.</p>
+<p>You can use <code>millSourcePath</code> to automatically set the source folders of your modules to match the build structure. You are not forced to rigidly use <code>millSourcePath</code> to define the source folders of all your code, but it can simplify the common case where you probably want your build-layout and on-disk-layout to be the same.</p>
+<p>E.g. for <code>mill.scalalib.ScalaModule</code>, the Scala source code is assumed by default to be in <code>millSourcePath/&quot;src&quot;</code> while resources are automatically assumed to be in <code>millSourcePath/&quot;resources&quot;</code>.</p>
+<p>You can override <code>millSourcePath</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object foo extends mill.Module {
+ def millSourcePath = super.millSourcePath / &quot;lols&quot;
+ def bar = T { &quot;hello&quot; }
+ object baz extends mill.Module {
+ def qux = T { &quot;world&quot; }
+ }
+}
+</code></pre>
+<p>And any overrides propagate down to the module's children: in the above example, module <code>foo</code> would have its <code>millSourcePath</code> be <code>./foo/lols</code> while module<code>foo.baz</code> would have its <code>millSourcePath</code> be <code>./foo/lols/baz</code>.</p>
+<p>Note that <code>millSourcePath</code> is generally only used for a module's input source files. Output is always in the <code>out/</code> folder and cannot be changed, e.g. even with the overriden <code>millSourcePath</code> the output paths are still the default <code>./out/foo/bar</code> and <code>./out/foo/baz/qux</code> folders.</p><h2 id="external-modules" class="Styles-hoverBox">External Modules<a href="#external-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Libraries for use in Mill can define <code>ExternalModule</code>s: <code>Module</code>s which are shared between all builds which use that library:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">package foo
+import mill._
+
+object Bar extends mill.define.ExternalModule {
+ def baz = T { 1 }
+ def qux() = T.command { println(baz() + 1) }
+
+ lazy val millDiscover = mill.define.Discover[this.type]
+}
+</code></pre>
+<p>In the above example, <code>foo.Bar</code> is an <code>ExternalModule</code> living within the <code>foo</code> Java package, containing the <code>baz</code> target and <code>qux</code> command. Those can be run from the command line via:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">mill foo.Bar/baz
+mill foo.Bar/qux
+</code></pre>
+<p><code>ExternalModule</code>s are useful for someone providing a library for use with Mill that is shared by the entire build: for example, <code>mill.scalalib.ZincWorkerApi/zincWorker</code> provides a shared Scala compilation service &amp; cache that is shared between all <code>ScalaModule</code>s, and <code>mill.scalalib.GenIdea/idea</code> lets you generate IntelliJ projects without needing to define your own <code>T.command</code> in your <code>build.sc</code> file</p><h2 id="foreign-modules" class="Styles-hoverBox">Foreign Modules<a href="#foreign-modules" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill can load other mill projects from external (or sub) folders, using Ammonite's <code>$file</code> magic import, allowing to depend on foreign modules. This allows, for instance, to depend on other projects' sources, or split your build logic into smaller files.</p>
+<p>For instance, assuming the following stucture : </p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">foo/
+ build.sc
+ bar/
+ build.sc
+baz/
+ build.sc
+</code></pre>
+<p>you can write the following in <code>foo/build.sc</code> : </p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">
+import $file.bar.build
+import $file.^.baz.build
+import mill._
+
+def someFoo = T {
+
+ ^.baz.build.someBaz(...)
+ bar.build.someBar(...)
+ ...
+}
+</code></pre>
+<p>The output of the foreign tasks will be cached under <code>foo/out/foreign-modules/</code>. </p><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="tasks.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Tasks</a><a href="cross-builds.html">Cross Builds <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/tasks.html b/page/tasks.html
new file mode 100644
index 00000000..864870f7
--- /dev/null
+++ b/page/tasks.html
@@ -0,0 +1,324 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Tasks</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#different-kinds-of-tasks">Different Kinds of Tasks</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#targets">Targets</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#sources">Sources</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#commands">Commands</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#task-context-api">Task Context API</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#millapictxdest">mill.api.Ctx.Dest</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#millapictxlog">mill.api.Ctx.Log</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#millapictxenv">mill.api.Ctx.Env</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#other-tasks">Other Tasks</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#anonymous-tasks">Anonymous Tasks</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#persistent-targets">Persistent Targets</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#inputs">Inputs</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#workers">Workers</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#cheat-sheet">Cheat Sheet</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Tasks</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="common-project-layouts.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Common Project Layouts</a><a href="modules.html">Modules <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div><p>One of Mill's core abstractions is its <em>Task Graph</em>: this is how Mill defines, orders and caches work it needs to do, and exists independently of any support for building Scala.</p>
+<p>The following is a simple self-contained example using Mill to compile Java:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">, mill._
+
+// sourceRoot -&gt; allSources -&gt; classFiles
+// |
+// v
+// resourceRoot ----&gt; jar
+
+def sourceRoot = T.sources { os.pwd / &#39;src }
+
+def resourceRoot = T.sources { os.pwd / &#39;resources }
+
+def allSources = T { sourceRoot().flatMap(p =&gt; os.walk(p.path)).map(PathRef(_)) }
+
+def classFiles = T {
+ os.makeDir.all(T.ctx().dest)
+
+ %(&quot;javac&quot;, allSources().map(_.path.toString()), &quot;-d&quot;, T.ctx().dest)(wd = T.ctx().dest)
+ PathRef(T.ctx().dest)
+}
+
+def jar = T { Jvm.createJar(Loose.Agg(classFiles().path) ++ resourceRoot().map(_.path)) }
+
+def run(mainClsName: String) = T.command {
+ os.proc(&#39;java, &quot;-cp&quot;, classFiles().path, mainClsName).call()
+}
+</code></pre>
+<p>Here, we have two <code>T.sources</code>s, <code>sourceRoot</code> and <code>resourceRoot</code>, which act as the roots of our task graph. <code>allSources</code> depends on <code>sourceRoot</code> by calling <code>sourceRoot()</code> to extract its value, <code>classFiles</code> depends on <code>allSources</code> the same way, and <code>jar</code> depends on both <code>classFiles</code> and <code>resourceRoot</code>.</p>
+<p>Filesystem operations in Mill are done using the <a href="http://ammonite.io/#Ammonite-Ops">Ammonite-Ops</a> library.</p>
+<p>The above build defines the following task graph:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">sourceRoot -&gt; allSources -&gt; classFiles
+ |
+ v
+ resourceRoot ----&gt; jar
+</code></pre>
+<p>When you first evaluate <code>jar</code> (e.g. via <code>mill jar</code> at the command line), it will evaluate all the defined targets: <code>sourceRoot</code>, <code>allSources</code>, <code>classFiles</code>, <code>resourceRoot</code> and <code>jar</code>.</p>
+<p>Subsequent <code>mill jar</code>s will evaluate only as much as is necessary, depending on what input sources changed:</p>
+<ul>
+ <li>
+ <p>If the files in <code>sourceRoot</code> change, it will re-evaluate <code>allSources</code>, compiling to <code>classFiles</code>, and building the <code>jar</code></p></li>
+ <li>
+ <p>If the files in <code>resourceRoot</code> change, it will only re-evaluate <code>jar</code> and use the cached output of <code>allSources</code> and <code>classFiles</code></p></li>
+</ul>
+<p>Apart from the <code>foo()</code> call-sites which define what each targets depend on, the code within each <code>T {...}</code> wrapper is arbitrary Scala code that can compute an arbitrary result from its inputs.</p><h2 id="different-kinds-of-tasks" class="Styles-hoverBox">Different Kinds of Tasks<a href="#different-kinds-of-tasks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>There are three primary kinds of <em>Tasks</em> that you should care about:</p>
+<ul>
+ <li><a href="#targets">Targets</a>, defined using <code>T {...}</code></li>
+ <li><a href="#sources">Sources</a>, defined using <code>T.sources {...}</code></li>
+ <li><a href="#commands">Commands</a>, defined using <code>T.command {...}</code></li>
+</ul><h3 id="targets" class="Styles-hoverBox">Targets<a href="#targets" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def allSources = T { os.walk(sourceRoot().path).map(PathRef(_)) }
+</code></pre>
+<p><code>Target</code>s are defined using the <code>def foo = T {...}</code> syntax, and dependencies on other targets are defined using <code>foo()</code> to extract the value from them. Apart from the <code>foo()</code> calls, the <code>T {...}</code> block contains arbitrary code that does some work and returns a result.</p>
+<p>Each target, e.g. <code>classFiles</code>, is assigned a path on disk as scratch space &amp; to store its output files at <code>out/classFiles/dest/</code>, and its returned metadata is automatically JSON-serialized and stored at <code>out/classFiles/meta.json</code>. The return-value of targets has to be JSON-serializable via <a href="https://github.com/lihaoyi/upickle">uPickle</a>.</p>
+<p>In case you want return your own case class (e.g. <code>MyCaseClass</code>), you can make it JSON-serializable by adding the following implicit def to its companion object:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">object MyCaseClass {
+ implicit def rw: upickle.default.ReadWriter[MyCaseClass] = upickle.default.macroRW
+}
+</code></pre>
+<p>If you want to return a file or a set of files as the result of a <code>Target</code>, write them to disk within your <code>T.ctx().dest</code> available through the <a href="#task-context-api">Task Context API</a> and return a <code>PathRef</code> to the files you wrote.</p>
+<p>If a target's inputs change but its output does not, e.g. someone changes a comment within the source files that doesn't affect the classfiles, then downstream targets do not re-evaluate. This is determined using the <code>.hashCode</code> of the Target's return value. For targets returning <code>ammonite.ops.Path</code>s that reference files on disk, you can wrap the <code>Path</code> in a <code>PathRef</code> (shown above) whose <code>.hashCode()</code> will include the hashes of all files on disk at time of creation.</p>
+<p>The graph of inter-dependent targets is evaluated in topological order; that means that the body of a target will not even begin to evaluate if one of its upstream dependencies has failed. This is unlike normal Scala functions: a plain old function <code>foo</code> would evaluate halfway and then blow up if one of <code>foo</code>'s dependencies throws an exception.</p>
+<p>Targets cannot take parameters and must be 0-argument <code>def</code>s defined directly within a <code>Module</code> body.</p><h3 id="sources" class="Styles-hoverBox">Sources<a href="#sources" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def sourceRootPath = os.pwd / &#39;src
+
+def sourceRoots = T.sources { sourceRootPath }
+</code></pre>
+<p><code>Source</code>s are defined using <code>T.sources { ... }</code>, taking one-or-more <code>ammonite.ops.Path</code>s as arguments. A <code>Source</code> is a subclass of <code>Target[Seq[PathRef]]</code>: this means that its build signature/<code>hashCode</code> depends not just on the path it refers to (e.g. <code>foo/bar/baz</code>) but also the MD5 hash of the filesystem tree under that path.</p>
+<p><code>T.sources</code> also has an overload which takes <code>Seq[PathRef]</code>, to let you override-and-extend source lists the same way you would any other <code>T {...}</code> definition:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def additionalSources = T.sources { os.pwd / &#39;additionalSources }
+def sourceRoots = T.sources { super.sourceRoots() ++ additionalSources() }
+</code></pre><h3 id="commands" class="Styles-hoverBox">Commands<a href="#commands" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def run(mainClsName: String) = T.command {
+ os.proc(&#39;java, &quot;-cp&quot;, classFiles().path, mainClsName).call()
+}
+</code></pre>
+<p>Defined using <code>T.command { ... }</code> syntax, <code>Command</code>s can run arbitrary code, with dependencies declared using the same <code>foo()</code> syntax (e.g. <code>classFiles()</code> above). Commands can be parametrized, but their output is not cached, so they will re-evaluate every time even if none of their inputs have changed.</p>
+<p>Like <a href="#targets">Targets</a>, a command only evaluates after all its upstream dependencies have completed, and will not begin to run if any upstream dependency has failed.</p>
+<p>Commands are assigned the same scratch/output folder <code>out/run/dest/</code> as Targets are, and its returned metadata stored at the same <code>out/run/meta.json</code> path for consumption by external tools.</p>
+<p>Commands can only be defined directly within a <code>Module</code> body.</p><h2 id="task-context-api" class="Styles-hoverBox">Task Context API<a href="#task-context-api" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>There are several APIs available to you within the body of a <code>T {...}</code> or <code>T.command {...}</code> block to help your write the code implementing your Target or Command:</p><h3 id="millapictxdest" class="Styles-hoverBox">mill.api.Ctx.Dest<a href="#millapictxdest" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><code>T.ctx().dest</code></li>
+ <li><code>implicitly[mill.api.Ctx.Dest]</code></li>
+</ul>
+<p>This is the unique <code>out/classFiles/dest/</code> path or <code>out/run/dest/</code> path that is assigned to every Target or Command. It is cleared before your task runs, and you can use it as a scratch space for temporary files or a place to put returned artifacts. This is guaranteed to be unique for every <code>Target</code> or <code>Command</code>, so you can be sure that you will not collide or interfere with anyone else writing to those same paths.</p><h3 id="millapictxlog" class="Styles-hoverBox">mill.api.Ctx.Log<a href="#millapictxlog" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><code>T.ctx().log</code></li>
+ <li><code>implicitly[mill.api.Ctx.Log]</code></li>
+</ul>
+<p>This is the default logger provided for every task. While your task is running, <code>System.out</code> and <code>System.in</code> are also redirected to this logger. The logs for a task are streamed to standard out/error as you would expect, but each task's specific output is also streamed to a log file on disk, e.g. <code>out/run/log</code> or <code>out/classFiles/log</code> for you to inspect later.</p>
+<p>Messages logged with <code>log.debug</code> appear by default only in the log files. You can use the <code>--debug</code> option when running mill to show them on the console too.</p><h3 id="millapictxenv" class="Styles-hoverBox">mill.api.Ctx.Env<a href="#millapictxenv" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li><code>T.ctx().env</code></li>
+ <li><code>implicitly[mill.api.Ctx.Env]</code></li>
+</ul>
+<p>Mill keeps a long-lived JVM server to avoid paying the cost of recurrent classloading. Because of this, running <code>System.getenv</code> in a task might not yield up to date environment variables, since it will be initialised when the server starts, rather than when the client executes. To circumvent this, mill's client sends the environment variables to the server as it sees them, and the server makes them available as a <code>Map[String, String]</code> via the <code>Ctx</code> API. </p>
+<p>If the intent is to always pull the latest environment values, the call should be wrapped in an <code>Input</code> as such : </p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def envVar = T.input { T.ctx().env.get(&quot;ENV_VAR&quot;) }
+</code></pre><h2 id="other-tasks" class="Styles-hoverBox">Other Tasks<a href="#other-tasks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<ul>
+ <li><a href="#anonymous-tasks">Anonymous Tasks</a>, defined using <code>T.task {...}</code></li>
+ <li><a href="#persistent-targets">Persistent Targets</a></li>
+ <li><a href="#inputs">Inputs</a></li>
+ <li><a href="#workers">Workers</a></li>
+</ul><h3 id="anonymous-tasks" class="Styles-hoverBox">Anonymous Tasks<a href="#anonymous-tasks" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def foo(x: Int) = T.task { ... x ... bar() ... }
+</code></pre>
+<p>You can define anonymous tasks using the <code>T.task { ... }</code> syntax. These are not runnable from the command-line, but can be used to share common code you find yourself repeating in <code>Target</code>s and <code>Command</code>s.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def downstreamTarget = T { ... foo() ... }
+def downstreamCommand = T.command { ... foo() ... }
+</code></pre>
+<p>Anonymous task's output does not need to be JSON-serializable, their output is not cached, and they can be defined with or without arguments. Unlike <a href="#targets">Targets</a> or <a href="#commands">Commands</a>, anonymous tasks can be defined anywhere and passed around any way you want, until you finally make use of them within a downstream target or command.</p>
+<p>While an anonymous task <code>foo</code>'s own output is not cached, if it is used in a downstream target <code>bar</code> and the upstream targets <code>baz</code> <code>qux</code> haven't changed, <code>bar</code>'s cached output will be used and <code>foo</code>'s evaluation will be skipped altogether.</p><h3 id="persistent-targets" class="Styles-hoverBox">Persistent Targets<a href="#persistent-targets" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def foo = T.persistent { ... }
+</code></pre>
+<p>Identical to <a href="#targets">Targets</a>, except that the <code>dest/</code> folder is not cleared in between runs.</p>
+<p>This is useful if you are running external incremental-compilers, such as Scala's <a href="https://github.com/sbt/zinc">Zinc</a>, Javascript's <a href="https://webpack.js.org/">WebPack</a>, which rely on filesystem caches to speed up incremental execution of their particular build step.</p>
+<p>Since Mill no longer forces a "clean slate" re-evaluation of <code>T.persistent</code> targets, it is up to you to ensure your code (or the third-party incremental compilers you rely on!) are deterministic. They should always converge to the same outputs for a given set of inputs, regardless of what builds and what filesystem states existed before.</p><h3 id="inputs" class="Styles-hoverBox">Inputs<a href="#inputs" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def foo = T.input { ... }
+</code></pre>
+<p>A generalization of <a href="#sources">Sources</a>, <code>T.input</code>s are tasks that re-evaluate <em>every time</em> (unlike <a href="#anonymous-tasks">Anonymous Tasks</a>), containing an arbitrary block of code.</p>
+<p>Inputs can be used to force re-evaluation of some external property that may affect your build. For example, if I have a <a href="#targets">Target</a> <code>bar</code> that makes use of the current git version:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def bar = T { ... os.proc(&quot;git&quot;, &quot;rev-parse&quot;, &quot;HEAD&quot;).call().out.string ... }
+</code></pre>
+<p><code>bar</code> will not know that <code>git rev-parse</code> can change, and will not know to re-evaluate when your <code>git rev-parse HEAD</code> <em>does</em> change. This means <code>bar</code> will continue to use any previously cached value, and <code>bar</code>'s output will be out of date!</p>
+<p>To fix this, you can wrap your <code>git rev-parse HEAD</code> in a <code>T.input</code>:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def foo = T.input { os.proc(&quot;git&quot;, &quot;rev-parse&quot;, &quot;HEAD&quot;).call().out.string }
+def bar = T { ... foo() ... }
+</code></pre>
+<p>This makes <code>foo</code> will always re-evaluate every build; if <code>git rev-parse HEAD</code> does not change, that will not invalidate <code>bar</code>'s caches. But if <code>git rev-parse
+HEAD</code> <em>does</em> change, <code>foo</code>'s output will change and <code>bar</code> will be correctly invalidated and re-compute using the new version of <code>foo</code>.</p>
+<p>Note that because <code>T.input</code>s re-evaluate every time, you should ensure that the code you put in <code>T.input</code> runs quickly. Ideally it should just be a simple check "did anything change?" and any heavy-lifting can be delegated to downstream targets.</p><h3 id="workers" class="Styles-hoverBox">Workers<a href="#workers" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">def foo = T.worker { ... }
+</code></pre>
+<p>Most tasks dispose of their in-memory return-value every evaluation; in the case of <a href="#targets">Targets</a>, this is stored on disk and loaded next time if necessary, while <a href="#commands">Commands</a> just re-compute them each time. Even if you use <code>--watch</code> or the Build REPL to keep the Mill process running, all this state is still discarded and re-built every evaluation.</p>
+<p>Workers are unique in that they store their in-memory return-value between evaluations. This makes them useful for storing in-memory caches or references to long-lived external worker processes that you can re-use.</p>
+<p>Mill uses workers to manage long-lived instances of the <a href="https://github.com/sbt/zinc">Zinc Incremental Scala Compiler</a> and the <a href="https://github.com/scala-js/scala-js">Scala.js Optimizer</a>. This lets us keep them in-memory with warm caches and fast incremental execution.</p>
+<p>Like <a href="#persistent-targets">Persistent Targets</a>, Workers inherently involve mutable state, and it is up to the implementation to ensure that this mutable state is only used for caching/performance and does not affect the externally-visible behavior of the worker.</p><h2 id="cheat-sheet" class="Styles-hoverBox">Cheat Sheet<a href="#cheat-sheet" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>The following table might help you make sense of the small collection of different Task types:</p><table class="table table-bordered">
+<thead>
+ <tr>
+ <th align="left"> </th>
+ <th align="left">Target </th>
+ <th align="left">Command </th>
+ <th align="left">Source/Input </th>
+ <th align="left">Anonymous Task </th>
+ <th align="left">Persistent Target </th>
+ <th align="left">Worker </th>
+ </tr>
+</thead>
+<tbody>
+ <tr>
+ <td align="left">Cached on Disk </td>
+ <td align="left">X </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ </tr>
+ <tr>
+ <td align="left">Must be JSON Writable </td>
+ <td align="left">X </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ </tr>
+ <tr>
+ <td align="left">Must be JSON Readable </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ </tr>
+ <tr>
+ <td align="left">Runnable from the Command Line </td>
+ <td align="left">X </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ </tr>
+ <tr>
+ <td align="left">Can Take Arguments </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ </tr>
+ <tr>
+ <td align="left">Cached between Evaluations </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left"> </td>
+ <td align="left">X </td>
+ </tr>
+</tbody></table><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="common-project-layouts.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Common Project Layouts</a><a href="modules.html">Modules <i class="fa fa-arrow-right" aria-hidden="true"></i></a></div></div></body></html> \ No newline at end of file
diff --git a/page/thirdparty-modules.html b/page/thirdparty-modules.html
new file mode 100644
index 00000000..52c8839f
--- /dev/null
+++ b/page/thirdparty-modules.html
@@ -0,0 +1,351 @@
+<html><head><meta charset="utf-8" /><link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" type="text/css" /><link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" /><link href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/styles/github-gist.min.css" rel="stylesheet" type="text/css" /><title>Thirdparty Modules</title><style>@media (min-width: 60em) {.WideStyles-header{
+ bottom: 0px;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ position: fixed;
+ top: 0px;
+ width: 25%;
+}
+
+.WideStyles-tableOfContentsItem{
+ display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+ width: 100%;
+}
+
+.WideStyles-tableOfContents{
+ display: flex;
+ flex-direction: column;
+ flex-grow: 1;
+ flex-shrink: 1;
+ min-height: 0px;
+ width: 100%;
+}
+
+.WideStyles-content{
+ box-sizing: border-box;
+ margin-left: 25%;
+ padding: 48px;
+}
+
+.WideStyles-footer{
+ bottom: 0px;
+ height: 50px;
+ position: fixed;
+ width: 25%;
+}
+
+.WideStyles-marginLeftZero{
+ margin-left: 0px;
+}
+}</style><style>@media (max-width: 60em) {.NarrowStyles-header{
+ margin-bottom: 10px;
+}
+
+.NarrowStyles-content{
+ padding: 16px;
+}
+
+.NarrowStyles-headerContent{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ width: 100%;
+}
+
+.NarrowStyles-flexFont{
+ font-size: 4vw;
+}
+
+.NarrowStyles-disappear{
+ display: none;
+}
+
+.NarrowStyles-floatLeft{
+ float: left;
+ margin-left: 30px;
+}
+}</style><style>.Styles-hoverBox{
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+.Styles-hoverBox:hover .Styles-hoverLink{
+ opacity: 0.5;
+}
+
+.Styles-hoverLink{
+ opacity: 0.1;
+}
+.Styles-hoverLink:hover{
+ opacity: 1.0;
+}
+
+.Styles-headerStyle{
+ background-color: rgb(61, 79, 93);
+ box-sizing: border-box;
+ display: flex;
+}
+
+.Styles-headerLinkBox{
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+}
+
+.Styles-headerLink{
+ align-items: center;
+ display: flex;
+ flex: 1;
+ justify-content: center;
+ padding: 10px 10px;
+}
+
+.Styles-footerStyle{
+ color: rgb(158, 167, 174);
+ display: flex;
+ justify-content: center;
+}
+
+.Styles-subtleLink{
+ text-decoration: none;
+}
+</style><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/highlight.min.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.1.0/languages/scala.min.js"></script><script>hljs.initHighlightingOnLoad();</script><meta name="viewport" content="initial-scale = 1.0,maximum-scale = 1.0" /></head><body style="margin: 0px;background-color: #f8f8f8;"><div class=" WideStyles-header NarrowStyles-header Styles-headerStyle"><div class=" NarrowStyles-headerContent"><h1 style="text-align: center;padding: 30px 30px;margin: 0px;"><a style="color: #f8f8f8;font-weight: bold;" href=".." class=" Styles-subtleLink NarrowStyles-flexFont"><img src="../logo-white.svg" style="height: 30px;margin-top: -5px;" /> Mill</a></h1><div class=" Styles-headerLinkBox"><div class=" WideStyles-tableOfContents" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Pages</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="../index.html">Intro to Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="configuring-mill.html">Configuring Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="common-project-layouts.html">Common Project Layouts</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="tasks.html">Tasks</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="modules.html">Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="cross-builds.html">Cross Builds</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="extending-mill.html">Extending Mill</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="mill-internals.html">Mill Internals</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="contrib-modules.html">Contrib Modules</a></li><li class=" WideStyles-marginLeftZero NarrowStyles-floatLeft"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="thirdparty-modules.html">Thirdparty Modules</a></li></ul></div></div></div></div><hr class=" NarrowStyles-disappear" style="background-color: #f8f8f8;width: 80%;" /><div class=" WideStyles-tableOfContents NarrowStyles-disappear" style="color: #f8f8f8;"><div style="padding-left: 40px;" class=" NarrowStyles-disappear"><b>Table of Contents</b></div><div style="overflow-y: auto;flex-shrink: 1;min-height: 0px;"><ul style="overflow: hidden;text-align: start;margin-top: 10px;white-space: nowrap;text-overflow: ellipsis;margin-right: 10px;"><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#aspectj">AspectJ</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration">Configuration</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#bash-completion">Bash Completion</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#dgraph">DGraph</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#ensime">Ensime</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#integration-testing-mill-plugins">Integration Testing Mill Plugins</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration-and-targets">Configuration and Targets</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#jbake">JBake</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#jbuildinfo">JBuildInfo</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#configuration-options">Configuration options</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#mill-wrapper-scripts">Mill Wrapper Scripts</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#how-it-works">How it works</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#use-cases">Use cases</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#osgi">OSGi</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li><li style="margin-left: 0px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#publishm2">PublishM2</a></li><li style="margin-left: 20px;"><a style="color: #f8f8f8;" class=" WideStyles-tableOfContentsItem" href="#quickstart">Quickstart</a></li></ul></div></div></div><div class=" WideStyles-content NarrowStyles-content" style="max-width: 900px;"><h1>Thirdparty Modules</h1><div style="margin-bottom: 10px;"><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="contrib-modules.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Contrib Modules</a><div></div></div></div><p>The modules (aka plugins) in this section are developed/maintained outside the mill git tree.</p>
+<p>Besides the documentation provided here, we urge you to consult the respective linked plugin documentation pages. The usage examples given here are most probably incomplete and sometimes outdated.</p>
+<p>If you develop or maintain a mill plugin, please create a <a href="https://github.com/lihaoyi/mill/pulls">pull request</a> to get your plugin listed here.</p><h2 id="aspectj" class="Styles-hoverBox">AspectJ<a href="#aspectj" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p><a href="https://projects.eclipse.org/projects/tools.aspectj">AspectJ compiler</a> support for mill.</p>
+<p>Project home: <a href="https://github.com/lefou/mill-aspectj">https://github.com/lefou/mill-aspectj</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._
+import mill.scalalib._
+import mill.define._
+
+// Load the plugin from Maven Central via ivy/coursier
+import $ivy.`de.tototec::de.tobiasroeser.mill.aspectj:0.1.0`, de.tobiasroeser.mill.aspectj._
+
+object main extends AspectjModule {
+
+ // Select the AspectJ version
+ def aspectjVersion = T{ &quot;{aspectjVersion}&quot; }
+
+ // Set AspectJ options, e.g. the language level and annotation processor
+ // Run `mill main.ajcHelp` to get a list of supported options
+ def ajcOptions = Seq(&quot;-8&quot;, &quot;-proc:none&quot;)
+
+}
+</code></pre><h3 id="configuration" class="Styles-hoverBox">Configuration<a href="#configuration" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Your module needs to extend <code>de.tobiasroeser.mill.aspectj.AspectjModule</code> which itself extends <code>mill.scalalib.JavaModule</code>.</p>
+<p>The module trait <code>de.tobiasroeser.mill.aspectj.AspectjModule</code> has various configuration options (over those from <code>mill.scalalib.JavaModule</code>).</p>
+<p>The most essential targets are:</p>
+<ul>
+ <li>
+ <p><code>def aspectjVersion: T[String]</code> - The AspectJ version. <em>Required</em>. For a list of available releases refer to the <a href="https://www.eclipse.org/aspectj/downloads.php">AspectJ Download Page</a>.</p></li>
+ <li>
+ <p><code>def ajcOptions: T[Seq[String]]</code> - Additional options to be used by <code>ajc</code> in the <code>compile</code> target.</p></li>
+ <li>
+ <p><code>def compile: T[CompilationResult]</code> - Compiles the source code with the ajc compiler.</p></li>
+</ul>
+<p>For a complete list of configuration options and more documentation, please refer to the <a href="https://github.com/lefou/mill-aspectj">project home page</a>.</p><h2 id="bash-completion" class="Styles-hoverBox">Bash Completion<a href="#bash-completion" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Limited bash completion support.</p>
+<p>Project home: <a href="https://github.com/lefou/mill-bash-completion">https://github.com/lefou/mill-bash-completion</a></p><h2 id="dgraph" class="Styles-hoverBox">DGraph<a href="#dgraph" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Show transitive dependencies of your build in your browser.</p>
+<p>Project home: <a href="https://github.com/ajrnz/mill-dgraph">https://github.com/ajrnz/mill-dgraph</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import $ivy.`com.github.ajrnz::mill-dgraph:0.2.0`
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="sh">sh&gt; mill plugin.dgraph.browseDeps(proj)()
+</code></pre><h2 id="ensime" class="Styles-hoverBox">Ensime<a href="#ensime" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Create an <a href="http://ensime.github.io/" title="ensime">.ensime</a> file for your build.</p>
+<p>Project home: <a href="https://github.com/yyadavalli/mill-ensime">https://github.com/yyadavalli/mill-ensime</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import $ivy.`fun.valycorp::mill-ensime:0.0.1`
+</code></pre>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="sh">sh&gt; mill fun.valycorp.mill.GenEnsime/ensimeConfig
+</code></pre><h2 id="integration-testing-mill-plugins" class="Styles-hoverBox">Integration Testing Mill Plugins<a href="#integration-testing-mill-plugins" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Integration testing for mill plugins.</p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>We assume, you have a mill plugin named <code>mill-demo</code></p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._, mill.scalalib._
+object demo extends ScalaModule with PublishModule {
+ // ...
+}
+</code></pre>
+<p>Add an new test sub-project, e.g. <code>it</code>.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import $ivy.`de.tototec::de.tobiasroeser.mill.integrationtest:0.1.0`
+import de.tobiasroeser.mill.integrationtest._
+
+object it extends MillIntegrationTest {
+
+ def millTestVersion = &quot;{exampleMillVersion}&quot;
+
+ def pluginsUnderTest = Seq(demo)
+
+}
+</code></pre>
+<p>Your project should now look similar to this:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="text">.
++-- demo/
+| +-- src/
+|
++-- it/
+ +-- src/
+ +-- 01-first-test/
+ | +-- build.sc
+ | +-- src/
+ |
+ +-- 02-second-test/
+ +-- build.sc
+</code></pre>
+<p>As the buildfiles <code>build.sc</code> in your test cases typically want to access the locally built plugin(s), the plugins publishes all plugins referenced under <code>pluginsUnderTest</code> to a temporary ivy repository, just before the test is executed. The mill version used in the integration test then used that temporary ivy repository.</p>
+<p>Instead of referring to your plugin with <code>import $ivy.&#39;your::plugin:version&#39;</code>, you can use the following line instead, which ensures you will use the correct locally build plugins.</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import $exec.plugins
+</code></pre>
+<p>Effectively, at execution time, this line gets replaced by the content of <code>plugins.sc</code>, a file which was generated just before the test started to execute.</p><h3 id="configuration-and-targets" class="Styles-hoverBox">Configuration and Targets<a href="#configuration-and-targets" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>The mill-integrationtest plugin provides the following targets.</p><h4 id="mandatory-configuration" class="Styles-hoverBox">Mandatory configuration<a href="#mandatory-configuration" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h4>
+<ul>
+ <li>
+ <p><code>def millTestVersion: T[String]</code> The mill version used for executing the test cases. Used by <code>downloadMillTestVersion</code> to automatically download.</p></li>
+ <li>
+ <p><code>def pluginsUnderTest: Seq[PublishModule]</code> - The plugins used in the integration test. You should at least add your plugin under test here. You can also add additional libraries, e.g. those that assist you in the test result validation (e.g. a local test support project). The defined modules will be published into a temporary ivy repository before the tests are executed. In your test <code>build.sc</code> file, instead of the typical <code>import $ivy.</code> line, you should use <code>import $exec.plugins</code> to include all plugins that are defined here.</p></li>
+</ul><h4 id="optional-configuration" class="Styles-hoverBox">Optional configuration<a href="#optional-configuration" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h4>
+<ul>
+ <li>
+ <p><code>def sources: Sources</code> - Locations where integration tests are located. Each integration test is a sub-directory, containing a complete test mill project.</p></li>
+ <li>
+ <p><code>def testCases: T[Seq[PathRef]]</code> - The directories each representing a mill test case. Derived from <code>sources</code>.</p></li>
+ <li>
+ <p><code>def testTargets: T[Seq[String]]</code> - The targets which are called to test the project. Defaults to <code>verify</code>, which should implement test result validation.</p></li>
+ <li>
+ <p><code>def downloadMillTestVersion: T[PathRef]</code> - Download the mill version as defined by <code>millTestVersion</code>. Override this, if you need to use a custom built mill version. Returns the <code>PathRef</code> to the mill executable (must have the executable flag).</p></li>
+</ul><h4 id="commands" class="Styles-hoverBox">Commands<a href="#commands" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h4>
+<ul>
+ <li><code>def test(): Command[Unit]</code> - Run the integration tests.</li>
+</ul><h2 id="jbake" class="Styles-hoverBox">JBake<a href="#jbake" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Create static sites/blogs with JBake.</p>
+<p>Plugin home: <a href="https://github.com/lefou/mill-jbake">https://github.com/lefou/mill-jbake</a></p>
+<p>JBake home: <a href="https://jbake.org">https://jbake.org</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import mill._
+import $ivy.`de.tototec::de.tobiasroeser.mill.jbake:0.1.0`
+import de.tobiasroeser.mill.jbake._
+
+object site extends JBakeModule {
+
+ def jbakeVersion = &quot;2.6.4&quot;
+
+}
+</code></pre>
+<p>Generate the site:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="sh">bash&gt; mill site.jbake
+</code></pre>
+<p>Start a local Web-Server on Port 8820 with the generated site:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="sh">bash&gt; mill site.jbakeServe
+</code></pre><h2 id="jbuildinfo" class="Styles-hoverBox">JBuildInfo<a href="#jbuildinfo" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>This is a <a href="https://www.lihaoyi.com/mill/">mill</a> module similar to <a href="https://www.lihaoyi.com/mill/page/contrib-modules.html#buildinfo">BuildInfo</a> but for Java. It will generate a Java class containing information from your build.</p>
+<p>Project home: <a href="https://github.com/carueda/mill-jbuildinfo">https://github.com/carueda/mill-jbuildinfo</a></p>
+<p>To declare a module that uses this plugin, extend the <code>com.github.carueda.mill.JBuildInfo</code> trait and provide the desired information via the <code>buildInfoMembers</code> method:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">// build.sc
+import $ivy.`com.github.carueda::jbuildinfo:0.1.2`
+import com.github.carueda.mill.JBuildInfo
+import mill.T
+
+object project extends JBuildInfo {
+ def buildInfoMembers: T[Map[String, String]] = T {
+ Map(
+ &quot;name&quot; -&gt; &quot;some name&quot;,
+ &quot;version&quot; -&gt; &quot;x.y.z&quot;
+ )
+ }
+}
+</code></pre>
+<p>This will generate:</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="java">// BuildInfo.java
+public class BuildInfo {
+ public static final String getName() { return &quot;some name&quot;; }
+ public static final String getVersion() { return &quot;x.y.z&quot;; }
+}
+</code></pre><h3 id="configuration-options" class="Styles-hoverBox">Configuration options<a href="#configuration-options" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<ul>
+ <li>
+ <p><code>def buildInfoMembers: T[Map[String, String]]</code></p>
+ <p>The map containing all member names and values for the generated class.</p>
+ </li>
+ <li>
+ <p><code>def buildInfoClassName: String</code>, default: <code>BuildInfo</code></p>
+ <p>The name of the class that will contain all the members from <code>buildInfoMembers</code>.</p>
+ </li>
+ <li>
+ <p><code>def buildInfoPackageName: Option[String]</code>, default: <code>None</code></p>
+ <p>The package name for the generated class.</p>
+ </li>
+</ul><h2 id="mill-wrapper-scripts" class="Styles-hoverBox">Mill Wrapper Scripts<a href="#mill-wrapper-scripts" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Small script to automatically fetch and execute mill build tool.</p>
+<p>Project home: <a href="https://github.com/lefou/millw">https://github.com/lefou/millw</a></p><h3 id="how-it-works" class="Styles-hoverBox">How it works<a href="#how-it-works" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p><code>millw</code> is a small wrapper script around mill and works almost identical to mill. It automatically downloads a mill release into <code>$HOME/.mill/download</code>.</p>
+<p>The mill version to be used will be determined by the following steps. The search ends, after the first step that results in a version.</p>
+<ul>
+ <li>If the first parameter is <code>--mill-version</code>, the second parameter will be used as the mill version. Example</li>
+</ul>
+<p><code>
+ sh $ mill --mill-version 0.3.6 --disable-ticker version
+ 0.3.6
+</code></p>
+<ul>
+ <li>If there is a file <code>.mill-version</code> in the working directory, it’s content will be used as mill version. The file must have only a mill version as content, no additional content or comments are supported. Example</li>
+</ul>
+<p><code>
+ sh $ echo -n &quot;0.3.6&quot; &gt; .mill-version
+ sh $ mill --disable-ticker version
+ 0.3.6
+</code></p>
+<p>The values of the <code>DEFAULT_MILL_VERSION</code> variable inside the script will be used.</p><h3 id="use-cases" class="Styles-hoverBox">Use cases<a href="#use-cases" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3><h4 id="as-mill-executable" class="Styles-hoverBox">As mill executable<a href="#as-mill-executable" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h4>
+<p>Istead of installing mill, you can just place the script into you local <code>$HOME/bin</code> directory and rename it to <code>mill</code>.</p>
+<p>If you need a special mill version in a project directory, just place a <code>.mill-version</code> file with the best mill version. Example: setting mill 0.3.6 as best local mill version</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="">sh $ echo -n &quot;0.3.6&quot; &gt; .mill-version
+</code></pre><h4 id="as-a-wrapper-script-in-your-project" class="Styles-hoverBox">As a wrapper script in your project<a href="#as-a-wrapper-script-in-your-project" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h4>
+<p>To make the start for others easier or to always have the correct mill version in your CI environment, you can just place a copy of the script as <code>millw</code> in your project root directory.</p>
+<p>You should change the <code>DEFAULT_MILL_VERSION</code> variable in that script to the correct version you want to use and add the file under version control.</p><h2 id="osgi" class="Styles-hoverBox">OSGi<a href="#osgi" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Produce OSGi Bundles with mill.</p>
+<p>Project home: <a href="https://github.com/lefou/mill-osgi">https://github.com/lefou/mill-osgi</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, mill.scalalib._
+import $ivy.`de.tototec::de.tobiasroeser.mill.osgi:0.0.5`
+import de.tobiasroeser.mill.osgi._
+
+object project extends ScalaModule with OsgiBundleModule {
+
+ def bundleSymbolicName = &quot;com.example.project&quot;
+
+ def osgiHeaders = T{ super.osgiHeaders().copy(
+ `Export-Package` = Seq(&quot;com.example.api&quot;),
+ `Bundle-Activator` = Some(&quot;com.example.internal.Activator&quot;)
+ )}
+
+ // other settings ...
+
+}
+</code></pre><h2 id="publishm2" class="Styles-hoverBox">PublishM2<a href="#publishm2" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h2>
+<p>Mill plugin to publish artifacts into a local Maven repository.</p>
+<p>Project home: <a href="https://github.com/lefou/mill-publishM2">https://github.com/lefou/mill-publishM2</a></p><h3 id="quickstart" class="Styles-hoverBox">Quickstart<a href="#quickstart" class=" Styles-hoverLink"><i class="fa fa-link" aria-hidden="true"></i></a></h3>
+<p>Just mix-in the <code>PublishM2Module</code> into your project. <code>PublishM2Module</code> already extends mill's built-in <code>PublishModule</code>.</p>
+<p>File: <code>build.sc</code></p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="scala">import mill._, scalalib._, publish._
+
+import $ivy.`de.tototec::de.tobiasroeser.mill.publishM2:0.0.1`
+import de.tobiasroeser.mill.publishM2._
+
+object project extends PublishModule with PublishM2Module {
+ // ...
+}
+</code></pre>
+<p>Publishing to default local Maven repository</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">&gt; mill project.publishM2Local
+[40/40] project.publishM2Local
+Publishing to /home/user/.m2/repository
+</code></pre>
+<p>Publishing to custom local Maven repository</p>
+<pre style="background-color: #f8f8f8"><code style="white-space:pre; background-color: #f8f8f8" class="bash">&gt; mill project.publishM2Local /tmp/m2repo
+[40/40] project.publishM2Local
+Publishing to /tmp/m2repo
+</code></pre><hr /><p><b>About the Author:</b><i> Haoyi is a software engineer, an early contributor to <a href="http://www.scala-js.org/">Scala.js</a>, and the author of many open-source Scala tools such as Mill, the <a href="http://lihaoyi.com/Ammonite">Ammonite REPL</a> and <a href="https://github.com/lihaoyi/fastparse">FastParse</a>. </i></p><p><i>If you've enjoy using Mill, or enjoyed using Haoyi's other open source libraries, please chip in (or get your Company to chip in!) via <a href="https://www.patreon.com/lihaoyi">Patreon</a> so he can continue his open-source work</i></p><hr /><div style="display: flex;flex-direction: row;justify-content: space-between;"><a href="contrib-modules.html"><i class="fa fa-arrow-left" aria-hidden="true"></i> Contrib Modules</a><div></div></div></div></body></html> \ No newline at end of file