1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt-doc.git synced 2025-04-24 19:47:11 -07:00

try to make site more intuitive

This commit is contained in:
Juan Liska 2016-01-05 05:23:50 -06:00
parent de753349e3
commit 6112dda189
5 changed files with 614 additions and 558 deletions

View file

@ -57,9 +57,7 @@
<!-- Main component for a primary marketing message or call to action --> <!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron"> <div class="jumbotron">
<h1>Kobalt</h1> <h1>Documentation</h1>
<p>A universal build system for the exigent developer.</p>
<img src="../pics/auto-completion.png" class="img-rounded"/>
<!-- <!--
<p> <p>
@ -71,47 +69,6 @@
<div class="col-md-9"> <div class="col-md-9">
<h2 class="section" id="downloading">Downloading and installing Kobalt</h2>
<p>
<a href="https://github.com/cbeust/kobalt/releases/latest">Download the zip file</a> then unzip it in a location we'll call <code>KOBALT_HOME</code>:
</p>
<pre class="brush:plain">
cd $KOBALT_HOME
unzip kobalt-xxx.zip
</pre>
<p>
Change to your project directory and call the <code>kobaltw</code> command with <code>--init</code>:
</p>
<pre class="brush:plain">
cd ~/java/project
$KOBALT_HOME/kobaltw --init
</pre>
<p>
This command will do two things:
</p>
<ol>
<li>Create a default <code>kobalt/src/Build.kt</code> file based on what was found there.
<li>Install the Kobalt Wrapper in your current directory (script `kobaltw`) and in the <code>kobalt/</code> directory. From now on, you can just use <code>./kobaltw</code> to build and you can ignore <code>$KOBALT_HOME</code>.
</ol>
<p>
You can now attempt to build your project with Kobalt:
</p>
<pre class="brush:plain">
./kobaltw assemble
</pre>
If your project follows a regular build structure (e.g. <a href="https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">Maven's hierarchy</a>), this should compile your file and create a .jar file. If not, you will have to make a few edits to your <code>Build.kt</code>.
As of this writing, Kobalt supports Java and Kotlin projects.
<h2 class="section" id="structure">Structure of a build file</h2> <h2 class="section" id="structure">Structure of a build file</h2>
<h3 class="section" indent="1" id="general-concepts">General concepts</h3> <h3 class="section" indent="1" id="general-concepts">General concepts</h3>
@ -628,7 +585,7 @@ If you are interested in discussing Kobalt related topics with other fellow user
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="../bootstrap/dist/js/bootstrap.min.js"></script> <script src="../bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../js/kobalt.js"></script> <script src="../js/kobalt.js"></script>
<script>generateKobalt(1);</script> <script>generateKobalt();</script>
<!-- <!--
<script src="../bootstrap/dist/js/docs.min.js"></script> <script src="../bootstrap/dist/js/docs.min.js"></script>

156
getting-started/index.html Normal file
View file

@ -0,0 +1,156 @@
<html>
<head>
<title>
Kobalt, by Cedric Beust
</title>
<script type="text/javascript" src="../sh/scripts/shCore.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushJScript.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushJava.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushPlain.js"></script>
<script>
SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.all();
</script>
<!--[if lt IE 9]><script src="../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
<!--
<script src="../bootstrap/assets/js/ie-emulation-modes-warning.js"></script>
-->
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- Favicons -->
<!--
<link rel="icon" href="/favicon.ico">
-->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-238215-6', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<div class="container">
<!-- Static navbar -->
<nav id="kobalt-navbar" class="navbar navbar-default">
</nav>
<!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>Kobalt</h1>
<p>A universal build system for the exigent developer.</p>
<img src="../pics/auto-completion.png" class="img-rounded"/>
<!--
<p>
<a class="btn btn-lg btn-primary" href="../../components/#navbar" role="button">Download &raquo;</a>
</p>
-->
</div>
<div class="col-md-9">
<h2 class="section" id="downloading">1. Download Kobalt</h2>
<p>
<a href="https://github.com/cbeust/kobalt/releases/latest">Download the zip file</a> then unzip it in a location we'll call <code>KOBALT_HOME</code>:
</p>
<pre class="brush:plain">
cd $KOBALT_HOME
unzip kobalt-xxx.zip
</pre>
<h2 class="section" id="downloading">2. Initialize your project for Kobalt</h2>
<p>
Change to your project directory and call the <code>kobaltw</code> command with <code>--init</code>:
</p>
<pre class="brush:plain">
cd ~/java/project
$KOBALT_HOME/kobaltw --init
</pre>
<p>
This command will do two things:
</p>
<ol>
<li>Create a default <code>kobalt/src/Build.kt</code> file based on what was found there.
<li>Install the Kobalt Wrapper in your current directory (script `kobaltw`) and in the <code>kobalt/</code> directory. From now on, you can just use <code>./kobaltw</code> to build and you can ignore <code>$KOBALT_HOME</code>.
</ol>
<p>
You can now attempt to build your project with Kobalt:
</p>
<pre class="brush:plain">
./kobaltw assemble
</pre>
If your project follows a regular build structure (e.g. <a href="https://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html">Maven's hierarchy</a>), this should compile your file and create a .jar file. If not, you will have to make a few edits to your <code>Build.kt</code>.
As of this writing, Kobalt supports Java and Kotlin projects.
<h2 class="section" id="structure">3. Edit Build.kt</h2>
<pre class="brush:java">
import com.beust.kobalt.*
import com.beust.kobalt.plugin.kotlin.kotlinProject
val kobalt = kotlinProject {
name = "kobalt"
group = "com.beust"
artifactId = name
version = "0.62"
directory = homeDir("kotlin/kobalt")
}
</pre>
</div>
<!-- Table of contents -->
<div class="col-md-3" id="table-of-contents">
</div>
</div> <!-- /container -->
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="../bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../js/kobalt.js"></script>
<script>generateKobalt(1);</script>
<!--
<script src="../bootstrap/dist/js/docs.min.js"></script>
-->
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<!--
<script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
-->
</body>

View file

@ -55,14 +55,20 @@
<!-- Main component for a primary marketing message or call to action --> <!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron"> <div class="jumbotron">
<h1>What is Kobalt?</h1> <h1>Kobalt: friendly, fast build system</h1>
<img src="../pics/auto-completion.png" class="img-rounded"/>
</div> </div>
<!-- Main content --> <!-- Main content -->
<div class="col-md-9"> <div class="col-md-9">
<h2 class="section" id="overview">Overview</h2> <h2 class="section" id="overview">Features</h2>
Kobalt is a build system system featuring build files written in Kotlin. It's focused on offering an intuitive DSL and plug-in architecture, fast builds and build file auto completion from your favorite IDE. <ul>
<li><h4>Intuitive DSL and plug-in architecture</h4></li>
<li><h4>Fast builds</h4></li>
<li><h4>Build file auto-completion from your favorite IDE</h4></li>
<li><h4>A cleaner syntax than Ant, Maven, Gradle, or SBT</h4></li>
</ul>
</p> </p>
<p> <p>
@ -123,10 +129,6 @@ Kobalt is currently in Beta but I'm already using it to build most of my project
<li>... and of course, <a href="https://github.com/cbeust/kobalt/blob/master/kobalt/src/Build.kt">Kobalt itself</a> (this build file demonstrates multi projects and project dependencies).</li> <li>... and of course, <a href="https://github.com/cbeust/kobalt/blob/master/kobalt/src/Build.kt">Kobalt itself</a> (this build file demonstrates multi projects and project dependencies).</li>
</ul> </ul>
<p>
Where to next? Are you interested in writing some cool Kotlin code and contribute to Kobalt? Or maybe just download and run Kobalt on your own projects just to get a feel for it? Then proceed to <a href="../documentation/index.html">Kobalt's main documentation!</a>
</p>
<p> <p>
</p> </p>
@ -142,7 +144,7 @@ Kobalt is currently in Beta but I'm already using it to build most of my project
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="../bootstrap/dist/js/bootstrap.min.js"></script> <script src="../bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../js/kobalt.js"></script> <script src="../js/kobalt.js"></script>
<script>generateKobalt(0);</script> <script>generateKobalt();</script>
<!-- <!--
<script src="../../assets/js/docs.min.js"></script> <script src="../../assets/js/docs.min.js"></script>

View file

@ -9,6 +9,14 @@ var content = [
url: "../home/index.html", url: "../home/index.html",
title: "Home" title: "Home"
}, },
{
url: "../getting-started/index.html",
title: "Getting Started"
},
{
url: "../idea-plug-in/index.html",
title: "IDEA plug-in"
},
{ {
url: "../documentation/index.html", url: "../documentation/index.html",
title: "Documentation" title: "Documentation"
@ -21,17 +29,9 @@ var content = [
url: "../plug-in-development/index.html", url: "../plug-in-development/index.html",
title: "Writing a Kobalt plug-in" title: "Writing a Kobalt plug-in"
}, },
{
url: "../idea-plug-in/index.html",
title: "IDEA plug-in"
},
{
url: "../ten-minutes/index.html",
title: "Ten minutes"
},
{ {
url: "../contributing/index.html", url: "../contributing/index.html",
title: "Contributing" title: "Contribute"
} }
]; ];
@ -50,14 +50,15 @@ var after = '</ul>'
+ '</nav>' + '</nav>'
; ;
function generateNavBar(index) { function generateNavBar() {
var result = before; var result = before;
for (var i = 0; i < content.length; i++) { for (var i = 0; i < content.length; i++) {
var cls = ""; var cls = "";
if (index == i) { var c = content[i];
var cleanUrl = c.url.replace("../", "")
if (window.location.href.indexOf(cleanUrl) > -1) {
cls = 'class="active"'; cls = 'class="active"';
} }
var c = content[i];
result += '<li ' + cls + '><a href="' + c.url + '">' + c.title + '</a></li>'; result += '<li ' + cls + '><a href="' + c.url + '">' + c.title + '</a></li>';
} }
result += after; result += after;

View file

@ -1,115 +1,57 @@
<html> <html>
<head> <head>
<title> <title>
Kobalt, by Cedric Beust Kobalt, by Cedric Beust
</title>
</title>
<script type="text/javascript" src="../sh/scripts/shCore.js"></script> <script type="text/javascript" src="../sh/scripts/shCore.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushJScript.js"></script> <script type="text/javascript" src="../sh/scripts/shBrushJScript.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushJava.js"></script> <script type="text/javascript" src="../sh/scripts/shBrushJava.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushPlain.js"></script> <script type="text/javascript" src="../sh/scripts/shBrushPlain.js"></script>
<script type="text/javascript" src="../sh/scripts/shBrushXml.js"></script> <script type="text/javascript" src="../sh/scripts/shBrushXml.js"></script>
<script> <script>
SyntaxHighlighter.defaults['gutter'] = false; SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.defaults['toolbar'] = false; SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.all(); SyntaxHighlighter.all();
</script> </script>
<!-- Optional Bootstrap Theme --> <!-- Optional Bootstrap Theme -->
<link href="data:text/css;charset=utf-8," data-href="../bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet" id="bs-theme-stylesheet"> <link href="data:text/css;charset=utf-8," data-href="../bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet" id="bs-theme-stylesheet">
<!--[if lt IE 9]><script src="../assets/js/ie8-responsive-file-warning.js"></script><![endif]-->
<!--
<!--[if lt IE 9]><script src="../assets/js/ie8-responsive-file-warning.js"></script><![endif]--> <script src="../bootstrap/assets/js/ie-emulation-modes-warning.js"></script>
<!-- -->
<script src="../bootstrap/assets/js/ie-emulation-modes-warning.js"></script> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
--> <!--[if lt IE 9]>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]--> <![endif]-->
<!-- Favicons -->
<!-- Favicons --> <!--
<!-- <link rel="icon" href="/favicon.ico">
<link rel="icon" href="/favicon.ico"> -->
--> </head>
<body>
</head>
<body>
<div class="container"> <div class="container">
<!-- Static navbar --> <!-- Static navbar -->
<nav id="kobalt-navbar" class="navbar navbar-default"> <nav id="kobalt-navbar" class="navbar navbar-default">
</nav> </nav>
<!-- Main component for a primary marketing message or call to action --> <!-- Main component for a primary marketing message or call to action -->
<div class="jumbotron"> <div class="jumbotron">
<h1>Plug-in development</h1> <h1>Plug-in development</h1>
<p>How to write a Kobalt plug-in.</p> <p>How to write a Kobalt plug-in.</p>
</div> </div>
<!-- Main content --> <!-- Main content -->
<div class="col-md-9"> <div class="col-md-9">
<h2 class="section" id="tutorial">Tutorial</h2>
<h2 class="section" id="introduction">Introduction</h2> <p>
<p>
Kobalt plug-ins are usually made of several parts:
<ul>
<li><a href="#plugin-xml"><b>kobalt-plugin.xml</b></a>. A file that describes all the components (called "plug-in actors") of your plug-in, such as contributors.</li>
<li><a href="#directives"><b>Directives</b></a>. Kotlin functions that users of your plug-in can invoke in their build file, such as <code>kotlinProject</code> or <code>dependencies</code>. These functions typically configure some data that your plug-in will later use to perform its functions.</li>
<li><a href="#tasks"><b>Tasks</b></a>. These tasks are invoked from the command line and ask your plug-ins to perform certain actions.</li>
<li><a href="#properties"><b>Properties</b></a>. Plug-ins can export properties and read properties from other plug-ins.</li>
</ul>
</p>
<p>
If you are curious to get a quick feel for what a Kobalt plug-in looks like, I suggest you go read how to If you are curious to get a quick feel for what a Kobalt plug-in looks like, I suggest you go read how to
<a href="../ten-minutes/index.html">write and publish a plug-in in ten minutes</a> and then you can come back here <a href="../ten-minutes/index.html">write and publish a plug-in in ten minutes</a> and then you can come back here
and keep reading. and keep reading.
</p> </p>
<h2 class="section" id="kobalt-plugin-xml">kobalt-plugin.xml</h2> <h2 class="section" id="philosophy">Plug-in architecture</h3>
<p> <p>
The <code>kobalt-plugin.xml</code> file (stored in <code>META-INF</code> in the jar file of your plug-in) is mandatory and describes all the actors of your plug-in. This file contains a list of class names, each of which is expected to implement at least one of <code>IPluginActor</code>'s interfaces: <p>
</p>
<pre class="brush:xml">
&lt;kobalt-plugin&gt;
&lt;name>kobalt&lt;/name&gt;
&lt;plugin-actors&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.android.AndroidPlugin&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.java.JavaBuildGenerator&lt;/class-name&gt;
&lt;/plugin-actors&gt;
&lt;/kobalt-plugin&gt;
</pre>
<p>
<code>IPluginActors</code> can be split in several categories:
</p>
<ul>
<li><strong>Plugins</strong>, which contain <code>@Task</code> annotations.</li>
<li><strong>Interceptors</strong>, which transform data that Kobalt gives them.</li>
<li><strong>Contributors</strong>, which produce additional data.</li>
</ul>
<p>
All plug-in actors are interfaces that extend <code>IPluginActor</code>. Plug-ins extend <code>IPlugin</code>,
interceptors extend <code>IInterceptor</code> and contributors extend <code>IContributor</code>. When Kobalt parses your
<code>kobalt-plugin.xml</code>, it instantiates all the classes found in the <code>&lt;plugin-actors&gt;</code> tag
and then introspects them to find out which <code>IPluginActor</code> interfaces that class implements.
</p>
<h3 class="section" id="philosophy">Plug-in architecture philosophy</h3>
<p>
<p>
Plug-ins often produce files and data that other plug-ins need to use in order for a build to succeed. For example, Plug-ins often produce files and data that other plug-ins need to use in order for a build to succeed. For example,
the Android plug-in needs to generate a file called <code>R.java</code> and then make this file available at the Android plug-in needs to generate a file called <code>R.java</code> and then make this file available at
compile time by the Java or Kotlin (or any other language) plug-in. Since plug-ins have no idea about what other compile time by the Java or Kotlin (or any other language) plug-in. Since plug-ins have no idea about what other
@ -117,15 +59,63 @@
Kobalt, Kobalt calls into them. This is done by declaring various "actors" that Kobalt will invoke whenever Kobalt, Kobalt calls into them. This is done by declaring various "actors" that Kobalt will invoke whenever
it needs the information that your plug-in produced. This is a design pattern often referred to as the it needs the information that your plug-in produced. This is a design pattern often referred to as the
<a href="https://en.wikipedia.org/wiki/Hollywood_principle">"Hollywood Principle"</a>: "Don't call us, we'll call you". <a href="https://en.wikipedia.org/wiki/Hollywood_principle">"Hollywood Principle"</a>: "Don't call us, we'll call you".
</p> </p>
<p> <p>
These "actors" are exactly what the <code>kobalt-plugin.xml</code> file describes. This file informs Kobalt about These "actors" are exactly what the <code>kobalt-plugin.xml</code> file describes. This file informs Kobalt about
the various ways in which your plug-in participates in the build system by specifying 1) plug-ins, 2) contributors the various ways in which your plug-in participates in the build system by specifying 1) plug-ins, 2) contributors
or 3) interceptors. or 3) interceptors.
</p>
</p>
</p> <h3 class="section" id="introduction" indent="1">Parts</h2>
</p> <p>
<ul>
<li><a href="#plugin-xml"><b>kobalt-plugin.xml</b></a>. A file that describes all the components (called "plug-in actors") of your plug-in, such as contributors.</li>
<li><a href="#directives"><b>Directives</b></a>. Kotlin functions that users of your plug-in can invoke in their build file, such as <code>kotlinProject</code> or <code>dependencies</code>. These functions typically configure some data that your plug-in will later use to perform its functions.</li>
<li><a href="#tasks"><b>Tasks</b></a>. These tasks are invoked from the command line and ask your plug-ins to perform certain actions.</li>
<li><a href="#properties"><b>Properties</b></a>. Plug-ins can export properties and read properties from other plug-ins.</li>
</ul>
</p>
<h3 class="section" id="kobalt-plugin-xml" indent="1">kobalt-plugin.xml</h2>
<p>
The <code>kobalt-plugin.xml</code> file (stored in <code>META-INF</code> in the jar file of your plug-in) is mandatory and describes all the actors of your plug-in. This file contains a list of class names, each of which is expected to implement at least one of <code>IPluginActor</code>'s interfaces:
</p>
<pre class="brush:xml">
&lt;plugin-actors&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.java.JavaPlugin&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.android.AndroidPlugin&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.java.JavaBuildGenerator&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.kotlin.KotlinBuildGenerator&lt;/class-name&gt;
&lt;/plugin-actors&gt;
</pre>
<p>
<code>IPluginActors</code> can be split in several categories:
</p>
<ul>
<li><strong>Plugins</strong>, which contain <code>@Task</code> annotations.</li>
<li><strong>Interceptors</strong>, which transform data that Kobalt gives them.</li>
<li><strong>Contributors</strong>, which produce additional data.</li>
</ul>
<p>
All plug-in actors are interfaces that extend <code>IPluginActor</code>. Plug-ins extend <code>IPlugin</code>,
interceptors extend <code>IInterceptor</code> and contributors extend <code>IContributor</code>. When Kobalt parses your
<code>kobalt-plugin.xml</code>, it instantiates all the classes found in the <code>&lt;plugin-actors&gt;</code> tag
and then introspects them to find out which <code>IPluginActor</code> interfaces that class implements.
</p>
<p>
If we look a the declarations of these classes, we can get an idea what they do
</p>
<pre class="brush:java">
class JavaPlugin : ICompilerContributor, IDocContributor {</pre>
<p>
With this declaration, we know that the <code>JavaPlugin</code> contributes a compiler and a doc generator.
</p>
<pre class="brush:java">
class JavaBuildGenerator: IInitContributor {</pre>
<p>
This class is declaring that it wants to take part in the <code>--init</code> selection process, discussed below.
</p>
<h2 class="section" id="actor-list">List of plug-in actors</h2> <h2 class="section" id="actor-list">List of plug-in actors</h2>
<p> <p>
Here is a list of actors (contributors and interceptors) that you can define in your plug-in. Here is a list of actors (contributors and interceptors) that you can define in your plug-in.
@ -159,7 +149,6 @@
<td> Classpath contributors let you specify additional jar files or directories that will be used by <td> Classpath contributors let you specify additional jar files or directories that will be used by
the <code>"compile"</code> task. the <code>"compile"</code> task.
</td> </td>
</tr> </tr>
<tr> <tr>
<td><code><a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/IClasspathInterceptor.kt">IClasspathInterceptor <td><code><a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/IClasspathInterceptor.kt">IClasspathInterceptor
@ -267,37 +256,6 @@
</td> </td>
</tr> </tr>
</table> </table>
<h2 class="section" id="example">Example</h2>
<p>
Kobalt itself uses a <code>kobalt-plugin.xml</code> to define contributors and interceptors, here is
an excerpt of it:
</p>
<pre class="brush:xml">
&lt;plugin-actors&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.java.JavaPlugin&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.android.AndroidPlugin&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.java.JavaBuildGenerator&lt;/class-name&gt;
&lt;class-name&gt;com.beust.kobalt.plugin.kotlin.KotlinBuildGenerator&lt;/class-name&gt;
&lt;/plugin-actors&gt;
</pre>
<p>
In order to find out what these actually do, we just need to take a look at their definition and
see which interfaces they implement. For example:
</p>
<pre class="brush:java">
class JavaPlugin : ICompilerContributor, IDocContributor {</pre>
<p>
With this declaration, we know that the <code>JavaPlugin</code> contributes a compiler and a doc generator.
</p>
<pre class="brush:java">
class JavaBuildGenerator: IInitContributor {</pre>
<p>
This class is declaring that it wants to take part in the <code>--init</code> selection process, which is
discussed in the next section.
</p>
<h2 class="section" id="selection-process">Selection process</h2> <h2 class="section" id="selection-process">Selection process</h2>
<p> <p>
Several plug-ins might want to contribute to a specific task where only one participant should be allowed, Several plug-ins might want to contribute to a specific task where only one participant should be allowed,
@ -323,45 +281,41 @@ interface IProjectAffinity {
For example, the JavaPlugin implements the <code><a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/ICompilerContributor.kt">ICompilerContributor</a></code> interface and then overrides For example, the JavaPlugin implements the <code><a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/ICompilerContributor.kt">ICompilerContributor</a></code> interface and then overrides
the <code>affinity()</code> method to make sure it gets run for Java projects but ignored for others: the <code>affinity()</code> method to make sure it gets run for Java projects but ignored for others:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
override fun affinity(project: Project, context: KobaltContext) = override fun affinity(project: Project, context: KobaltContext) =
if (project.sourceSuffix == ".java") 1 else 0</pre> if (project.sourceSuffix == ".java") 1 else 0</pre>
<h2 class="section" id="directives">Directives</h2>
<p>
<h2 class="section" id="directives">Directives</h2>
<p>
Directives are functions that users of your plug-in can use in their build file in order to configure your plug-in. These can be any kind of Kotlin function but in the interest of preserving a clean syntax in the build file, it's recommended to use the type safe builder pattern, <a href="https://kotlinlang.org/docs/reference/type-safe-builders.html">as described here</a>. Directives are functions that users of your plug-in can use in their build file in order to configure your plug-in. These can be any kind of Kotlin function but in the interest of preserving a clean syntax in the build file, it's recommended to use the type safe builder pattern, <a href="https://kotlinlang.org/docs/reference/type-safe-builders.html">as described here</a>.
</p> </p>
<p> <p>
Imagine that you want to offer a boolean parameter <code>publish</code> to users of your plug-in, you start by creating a class to hold that parameter: Imagine that you want to offer a boolean parameter <code>publish</code> to users of your plug-in, you start by creating a class to hold that parameter:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
class Info(val publish: Boolean) class Info(val publish: Boolean)
</pre> </pre>
<p> <p>
Next, you create a directive that returns such a class and which also allows to configure it via the type safe builder pattern: Next, you create a directive that returns such a class and which also allows to configure it via the type safe builder pattern:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
@Directive @Directive
public fun myConfig(init: Info.() -> Unit) = Info().apply { init() }</pre> public fun myConfig(init: Info.() -> Unit) = Info().apply { init() }</pre>
<p> <p>
The <code>@Directive</code> annotation is not enforced but you should always use it in order to help future tools (e.g. an IDEA plug-in) identify Kobalt directives so they can be treated differently from regular Kotlin functions. The code above defines a <code>myConfig</code> function that accepts a closure as an argument. It creates an <code>Info</code> The <code>@Directive</code> annotation is not enforced but you should always use it in order to help future tools (e.g. an IDEA plug-in) identify Kobalt directives so they can be treated differently from regular Kotlin functions. The code above defines a <code>myConfig</code> function that accepts a closure as an argument. It creates an <code>Info</code>
object, calls the <code>init()</code> function on it (which runs all the code inside that closure) and then return that <code>Info</code> object. object, calls the <code>init()</code> function on it (which runs all the code inside that closure) and then return that <code>Info</code> object.
</p> </p>
<p> <p>
Users can now specify the following in their build file: Users can now specify the following in their build file:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
// Build.kt // Build.kt
<imp></imp>ort.com.example.plugin.myConfig <imp></imp>ort.com.example.plugin.myConfig
myConfig { myConfig {
publish = true publish = true
}</pre> }</pre>
<p> <p>
If you need access to the project being built, just declare an additional parameter of type <code>Project</code> to your directive and have the user pass that project: If you need access to the project being built, just declare an additional parameter of type <code>Project</code> to your directive and have the user pass that project:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
@Directive @Directive
public fun myConfig(project: Project, init: Info.() -> Unit) : Info { public fun myConfig(project: Project, init: Info.() -> Unit) : Info {
@ -372,10 +326,9 @@ myConfig(project) {
publish = true publish = true
} }
</pre> </pre>
<p> <p>
The last piece of this puzzle is how you give this data back to your plug-in so it can act on it. In order to do this, you simply look up the name of your plug-in in the <code>Plugins</code> registry and invoke whatever function you need to run: The last piece of this puzzle is how you give this data back to your plug-in so it can act on it. In order to do this, you simply look up the name of your plug-in in the <code>Plugins</code> registry and invoke whatever function you need to run:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
@Directive @Directive
public fun myConfig(init: Info.() -> Unit) = Info().apply { public fun myConfig(init: Info.() -> Unit) = Info().apply {
@ -383,19 +336,19 @@ public fun myConfig(init: Info.() -> Unit) = Info().apply {
(Kobalt.findPlugin("my-plug-in") as MyPlugin).info = info (Kobalt.findPlugin("my-plug-in") as MyPlugin).info = info
this this
}</pre> }</pre>
<p> <p>
Obviously, you can choose any kind of API to communicate between the directive and its plug-in. In the code Obviously, you can choose any kind of API to communicate between the directive and its plug-in. In the code
above, I chose to directly override the entire <code>Info</code> field, but you could instead choose to call above, I chose to directly override the entire <code>Info</code> field, but you could instead choose to call
a function, just set one boolean instead of the whole object, etc... a function, just set one boolean instead of the whole object, etc...
</p> </p>
<h2 class="section" id="tasks">Tasks</h2> <h2 class="section" id="tasks">Tasks</h2>
<p> <p>
Tasks are provided by plug-ins and can be invoked from the command line, e.g. <code>./kobaltw assemble</code>. There are two kinds of tasks: static and dynamic. Tasks are provided by plug-ins and can be invoked from the command line, e.g. <code>./kobaltw assemble</code>. There are two kinds of tasks: static and dynamic.
</p> </p>
<h3 class="section" indent="1">Static tasks</h3> <h3 class="section" indent="1">Static tasks</h3>
<p> <p>
Static tasks are functions declared directly in your plug-in class and annotated with the <code>@Task</code> annotation. Here is an example: Static tasks are functions declared directly in your plug-in class and annotated with the <code>@Task</code> annotation. Here is an example:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
@Task(name = "lineCount", description = "Count the lines", runBefore = arrayOf("compile")) @Task(name = "lineCount", description = "Count the lines", runBefore = arrayOf("compile"))
fun lineCount(project: Project): TaskResult { fun lineCount(project: Project): TaskResult {
@ -403,11 +356,10 @@ fun lineCount(project: Project): TaskResult {
return TaskResult() return TaskResult()
} }
</pre> </pre>
<p> <p>
A Kobalt task needs to accept a <code>Project</code> in parameter and return a <code>TaskResult</code>, which indicates whether this task completed successfully. A Kobalt task needs to accept a <code>Project</code> in parameter and return a <code>TaskResult</code>, which indicates whether this task completed successfully.
</p> </p>
<p>
<p>
The <code>@Task</code> annotation accepts the following attributes: The <code>@Task</code> annotation accepts the following attributes:
<dl class="dl-horizontal"> <dl class="dl-horizontal">
<dt>name</dt> <dt>name</dt>
@ -421,22 +373,22 @@ fun lineCount(project: Project): TaskResult {
<dt>alwaysRunAfter</dt> <dt>alwaysRunAfter</dt>
<dd>A list of all the tasks that will always be run after this task if it's invoked.</dd> <dd>A list of all the tasks that will always be run after this task if it's invoked.</dd>
</dl> </dl>
</p> </p>
<p> <p>
The difference between <code>runAfter</code> and <code>alwaysRunAfter</code> is subtle but important. <code>runAfter</code> The difference between <code>runAfter</code> and <code>alwaysRunAfter</code> is subtle but important. <code>runAfter</code>
is just a declaration of dependency. It's basically the reverse of <code>runBefore</code> but it's useful in case is just a declaration of dependency. It's basically the reverse of <code>runBefore</code> but it's useful in case
you are not the author of the task you want to run before (if you were, you would just use the <code>runBefore</code> you are not the author of the task you want to run before (if you were, you would just use the <code>runBefore</code>
annotation on it). Since you can't say <code>"a runBefore b"</code> because you don't own task "a", annotation on it). Since you can't say <code>"a runBefore b"</code> because you don't own task "a",
you say <code>"b runAfter a"</code>. you say <code>"b runAfter a"</code>.
</p> </p>
<p> <p>
For example, <code>compileTest</code> is declared as a <code>runAfter</code> for the task <code>compile</code>. For example, <code>compileTest</code> is declared as a <code>runAfter</code> for the task <code>compile</code>.
This means that it doesn't make sense to run <code>compileTest</code> unless <code>compile</code> has run first. This means that it doesn't make sense to run <code>compileTest</code> unless <code>compile</code> has run first.
However, if a user invokes the task <code>compile</code>, they probably don't want to invoke <code>compileTest</code>, However, if a user invokes the task <code>compile</code>, they probably don't want to invoke <code>compileTest</code>,
so a dependency is exactly what we need here: invoking <code>compileTest</code> will trigger <code>compile</code> so a dependency is exactly what we need here: invoking <code>compileTest</code> will trigger <code>compile</code>
but not the other way around. but not the other way around.
</p> </p>
<p> <p>
However, there are times where you want to define a task that will <strong>always</strong> run after a given task. However, there are times where you want to define a task that will <strong>always</strong> run after a given task.
For example, you could have a <code>signJarFile</code> task that should always be invoked if someone builds a jar For example, you could have a <code>signJarFile</code> task that should always be invoked if someone builds a jar
file. You don't expect users to invoke that target explicitly, but whenever they invoke the <code>assemble</code> file. You don't expect users to invoke that target explicitly, but whenever they invoke the <code>assemble</code>
@ -444,19 +396,18 @@ fun lineCount(project: Project): TaskResult {
even if the user didn't explicitly request it, you should use <code>alwaysRunAfter</code>. even if the user didn't explicitly request it, you should use <code>alwaysRunAfter</code>.
Note that there is no <code>alwaysRunBefore</code> annotation since <code>runBefore</code> Note that there is no <code>alwaysRunBefore</code> annotation since <code>runBefore</code>
achieves the same functionality. achieves the same functionality.
</p> </p>
<p> <p>
Here are a few different scenarios to illustrate how the three attributes work for the task <code>exampleTask</code>: Here are a few different scenarios to illustrate how the three attributes work for the task <code>exampleTask</code>:
</p> </p>
<p align="center"> <p align="center">
<strong>Result of the command <code>./kobaltw --dryRun compile</code></strong> <strong>Result of the command <code>./kobaltw --dryRun compile</code></strong>
</p> </p>
<table width="100%" class="table table-bordered table-condensed"> <table width="100%" class="table table-bordered table-condensed">
<thead> <thead>
<td align="center">Configuration for <code>exampleTask</code></td> <td align="center">Configuration for <code>exampleTask</code></td>
<td align="center">Result</td> <td align="center">Result</td>
</thead> </thead>
<tr> <tr>
<td align="center">runBefore = "compile"</td> <td align="center">runBefore = "compile"</td>
<td> <td>
@ -480,23 +431,21 @@ kobalt-line-count:compile
kobalt-line-count:exampleTask</pre> kobalt-line-count:exampleTask</pre>
</td> </td>
</tr> </tr>
</table> </table>
<h3 class="section" indent="1">Dynamic tasks</h3>
<h3 class="section" indent="1">Dynamic tasks</h3> <p>
<p>
Dynamic tasks are useful when you want your plug-in to generate one or several tasks that depend on Dynamic tasks are useful when you want your plug-in to generate one or several tasks that depend on
some other runtime information (therefore, you can't declare a method and put a <code>@Task</code> some other runtime information (therefore, you can't declare a method and put a <code>@Task</code>
annotation on it). Plug-ins declare dynamic tasks by implementing the <code>ITaskContributor</code> annotation on it). Plug-ins declare dynamic tasks by implementing the <code>ITaskContributor</code>
intrface: intrface:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
interface ITaskContributor { interface ITaskContributor {
fun tasksFor(context: KobaltContext) : List&lt;DynamicTask&gt; fun tasksFor(context: KobaltContext) : List&lt;DynamicTask&gt;
}</pre> }</pre>
<p> <p>
For example: For example:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
override fun tasksFor(context: KobaltContext) = listOf( override fun tasksFor(context: KobaltContext) = listOf(
DynamicTask( DynamicTask(
@ -506,16 +455,16 @@ override fun tasksFor(context: KobaltContext) = listOf(
closure = { project: Project -> closure = { project: Project ->
println("Running dynamicTask") println("Running dynamicTask")
TaskResult() TaskResult()
}))</pre> }))</pre>
<p> <p>
<code>DynamicTask</code> mirrors the <code>@Task</code> attributes: <code>name</code>, <code>description</code> and <code>DynamicTask</code> mirrors the <code>@Task</code> attributes: <code>name</code>, <code>description</code> and
dependencies. The only addition is the <code>closure</code> parameter, which specifics the code that will dependencies. The only addition is the <code>closure</code> parameter, which specifics the code that will
run if your task gets invoked. That closure needs to follow the same constraints that a <code>@Task</code> method run if your task gets invoked. That closure needs to follow the same constraints that a <code>@Task</code> method
obeys: it takes a <code>Project</code> parameter and returns a <code>TaskResult</code>. obeys: it takes a <code>Project</code> parameter and returns a <code>TaskResult</code>.
</p> </p>
<p> <p>
Once you have implemented <code>ITaskContributor</code>, you can see your dynamic task in the list of tasks and run it directly: Once you have implemented <code>ITaskContributor</code>, you can see your dynamic task in the list of tasks and run it directly:
</p> </p>
<pre class="brush:plain"> <pre class="brush:plain">
$ ./kobaltw --tasks $ ./kobaltw --tasks
===== kobalt-line-count ===== ===== kobalt-line-count =====
@ -524,9 +473,8 @@ $ ./kobaltw --tasks
$ ./kobaltw dynamicTask $ ./kobaltw dynamicTask
Running dynamictask Running dynamictask
</pre> </pre>
<h2 class="section" id="properties">Properties</h2>
<h2 class="section" id="properties">Properties</h2> <p>
<p>
Properties are the mechanism that plug-ins can use to export values and also read values that other Properties are the mechanism that plug-ins can use to export values and also read values that other
plug-ins have exported. There are two kinds of properties that plug-ins can manipulate: plug-ins have exported. There are two kinds of properties that plug-ins can manipulate:
</p> </p>
@ -536,7 +484,6 @@ Running dynamictask
in particular.</li> in particular.</li>
</ul> </ul>
<h3 class="section" indent="1" id="project-properties">Project properties</h3> <h3 class="section" indent="1" id="project-properties">Project properties</h3>
<p> <p>
<code>Project</code> instances have a property called <code>projectProperties</code> that is an <code>Project</code> instances have a property called <code>projectProperties</code> that is an
instance of the <code>ProjectProperties</code> class. Plugins can put and get values on this instance of the <code>ProjectProperties</code> class. Plugins can put and get values on this
@ -545,55 +492,48 @@ Running dynamictask
<pre class="brush:java"> <pre class="brush:java">
fun taskAssemble(project: Project) : TaskResult { fun taskAssemble(project: Project) : TaskResult {
project.projectProperties.put(PACKAGES, packages) project.projectProperties.put(PACKAGES, packages)
</pre> </pre>
<h3 class="section" indent="1" id="plugin-properties">Plug-in properties</h3> <h3 class="section" indent="1" id="plugin-properties">Plug-in properties</h3>
<p> <p>
The <code>PluginProperties</code> instance can be found on the <code>KobaltContext</code> The <code>PluginProperties</code> instance can be found on the <code>KobaltContext</code>
object that your plug-in receives in its <code>apply()</code> method. Once you have an instance of this object that your plug-in receives in its <code>apply()</code> method. Once you have an instance of this
class, you can read or write variables into it: class, you can read or write variables into it:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
override fun apply(project: Project, context: KobaltContext) { override fun apply(project: Project, context: KobaltContext) {
// Export a property for other plug-ins to use // Export a property for other plug-ins to use
context.pluginProperties.put(PLUGIN_NAME, "somePluginProperty", "someValue") context.pluginProperties.put(PLUGIN_NAME, "somePluginProperty", "someValue")
// Read a property from another plug-in // Read a property from another plug-in
val sourceDir = context.pluginProperties.get("pluginName", "somePluginProperty") val sourceDir = context.pluginProperties.get("pluginName", "somePluginProperty")
} }
</pre> </pre>
<h3 class="section" indent="1" id="documenting-properties">Documenting properties</h3> <h3 class="section" indent="1" id="documenting-properties">Documenting properties</h3>
<p> <p>
Plug-ins that define properties should annotate them with the <code>@ExportedPluginProperty</code> or Plug-ins that define properties should annotate them with the <code>@ExportedPluginProperty</code> or
<code>@ExportedProjectProperty</code>annotation: <code>@ExportedProjectProperty</code>annotation:
</p> </p>
<pre class="brush:java"> <pre class="brush:java">
companion object { companion object {
@ExportedProjectProperty @ExportedProjectProperty
const val BUILD_DIR = "buildDir" const val BUILD_DIR = "buildDir"
</pre> </pre>
</div> </div>
<!-- Table of contents --> <!-- Table of contents -->
<div class="col-md-3" id="table-of-contents"> <div class="col-md-3" id="table-of-contents">
</div> </div>
<!-- Bootstrap core JavaScript <!-- Bootstrap core JavaScript
================================================== --> ================================================== -->
<!-- Placed at the end of the document so the pages load faster --> <!-- Placed at the end of the document so the pages load faster -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="../bootstrap/dist/js/bootstrap.min.js"></script> <script src="../bootstrap/dist/js/bootstrap.min.js"></script>
<script src="../js/kobalt.js"></script> <script src="../js/kobalt.js"></script>
<script>generateKobalt(3);</script> <script>generateKobalt();</script>
<!--
<!--
<script src="../bootstrap/dist/js/docs.min.js"></script> <script src="../bootstrap/dist/js/docs.min.js"></script>
--> -->
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<!-- <!--
<script src="../../assets/js/ie10-viewport-bug-workaround.js"></script> <script src="../../assets/js/ie10-viewport-bug-workaround.js"></script>
--> -->
</div> </div>
</body> </body>