1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt-doc.git synced 2025-04-25 12:07:10 -07:00

Merge branch 'master' of github.com:cbeust/kobalt-doc

This commit is contained in:
Cedric Beust 2015-11-27 05:19:53 -08:00
commit 753254d7a5
11 changed files with 354 additions and 135 deletions

141
contributing/index.html Normal file
View file

@ -0,0 +1,141 @@
<html>
<head>
<title>
Kobalt, by Cedric Beust
</title>
<!-- Bootstrap core CSS -->
<link href="../bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/kobalt.css" rel="stylesheet" />
<!-- 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">
<!--[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">
-->
</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>Contributing to Kobalt</h1>
<p>Interested in contributing to Kobalt? This page explains how to configure your development environment.</p>
</div>
<!-- Main content -->
<div class="col-md-9">
<h2 class="section" id="launch_configuration">Launch configuration</h2>
<p>
Kobalt's main class is `com.beust.kobalt.MainKt`. Here is a typical launch configuration:
</p>
<p align="center">
<img width="99%" class="img-rounded" src="../pics/launch-configuration.png"/>
</p>
<p>
A few observations:
<ul>
<li>You can ask Kobalt to build external projects by specifying a non-empty "Working Directory".</li>
<li>The default log level is 1. 2 is useful for debugging and 3 will be extremely verbose.</li>
<li>Another command line parameter worth of notice is <code>--dev</code>, which will add the class
name and thread information to each log line.</li>
<li>Checking the "Single instance" box is useful to avoid duplicating these launch configurations.</li>
</ul>
</p>
<h2 class="section" id="build-file">Auto complete in build files</h2>
<p>
It's useful to turn on auto completion for your <code>Build.kt</code> file if you are adding new
elements to the DSL. You can achieve this in two steps.
</p>
<h3 class="section" id="sync" indent="1">Sync your build file</h3>
<p>
This is achieved with the <code>Kobalt / Sync build file</code> menu item. On top of configuring your
IDEA project with the correct dependencies, this will also add the <code>kobalt.jar</code> file to your
classpath.
</p>
<p align="center" class="img-rounded">
<img width="50%" class="img-rounded" src="../pics/menu-sync.png"/>
</p>
<p align="center" class="img-rounded">
<img width="50%" class="img-rounded" src="../pics/kobalt-jar.png"/>
</p>
<h3 class="section" id="compile-build-file" indent="1">Compile your build file</h3>
<p>
Next, mark the directory that contains your build file as a "Source directory":
</p>
<p align="center" class="img-rounded">
<img width="50%" class="img-rounded" src="../pics/source-root.png"/>
</p>
<div class="bs-callout bs-callout-warning">
<h4>Alternate source directory for <code>Build.kt</code></h4>
The default location for <code>Build.kt</code> is in the root directory of your project but
you can also put it in <code>kobalt/src/Build.kt</code> and then mark that directory as
a source directory.
</div>
<p>
You can now use all the IDEA features on your build file:
</p>
<p align="center">
<img class="img-rounded" src="../pics/auto-complete.png"/>
</p>
</div>
<!-- Table of contents -->
<div class="col-md-3" id="table-of-contents">
</div>
<!-- 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(6);</script>
<!--
<script src="../../assets/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

@ -129,6 +129,34 @@ Here are a few noteworthy details about this small build file:
<li>The functions <code>kotlinProject</code> and <code>homeDir</code> are supplied by Kobalt and are referred to as "directives"
</ul>
<p>
In terms of syntax, there are basically three different ways to specify values in a build file:
</p>
<ul>
<li>Individual values for primitives (numbers, strings) are a straight equals sign:
<pre>
name = "kobalt"</pre>
</li>
<li>
Parameters that can receive multiple values are usually captured by function calls, so you use parentheses, as usual in Kotlin:
<pre>
compile("dep1", "dep2", "dep2")</pre>
</li>
<li>
Complex objects are passed as closures, so you use curly braces to define them:
<pre>
dependencies {
...
}</pre>
</li>
</ul>
<p>
Remember that a build file is a valid Kotlin source, so you can use function calls instead of literal values, or any other correct Kotlin code in your build file:
</p>
<pre>
version = readVersion()</pre>
<h3 class="section" indent="1" id="directives">Directives</h3>
<p>
@ -143,6 +171,7 @@ val kobalt = kotlinProject {
<b>
assemble {
jar {
}
}
</b>
}
@ -436,132 +465,42 @@ Now, all you need to do is to upload your package:
./kobaltw uploadJcenter
</pre>
<h2 class="section" id="writing-a-plug-in">Writing a plug-in</h2>
A good starting point to write a plug-in is the <a href="https://github.com/cbeust/kobalt-line-count">kobalt-line-count project</a>, which shows a minimalistic plug-in.
<h3 class="section" indent="1" id="building">Building</h3>
You only need to do two things to build a Kobalt plug-in:
<h4>1. Add Kobalt as a dependency:</h4>
<h2 class="section" id="profiles">Profiles</h2>
<p>
Profiles allow you to run altered versions of your build file by using command
line parameters.
</p>
<p>
You start by defining boolean values initialized to <code>false</code> in your build file:
</p>
<pre>
val experimental = false
val premium = false
</pre>
<p>
Then you use this variable wherever you need it in your build file:
</p>
<pre>
val p = javaProject {
name = if (experimental) "project-exp" else "project"
version = "1.3"
</pre>
<p>
Finally, you invoke <code>./kobaltw</code> with the <code>--profiles</code> parameter followed by the profiles you want to activate, separated by a comma:
</p>
<pre>
./kobaltw -profiles experimental,premium assemble
</pre>
<p>
Keep in mind that since your build file is a real Kotlin source file,
you can use these profile variables pretty much anywhere, e.g.:
</p>
<pre>
dependencies {
compile("com.beust:kobalt:0.61")
}
</pre>
<h4>2. Declare the main class of your plug-in in the Jar file's manifest:</h4>
<pre>
packaging {
jar {
manifest {
attributes("Kobalt-Plugin-Class", "com.beust.kobalt.example.ExamplePlugin")
}
}
</pre>
<h3 class="section" indent="1" id="implementing">Implementing</h3>
A plug-in typically has three components:
<ul>
<li>Extending and implementing the methods of <code>BasePlugin</code>.
<li>Specifying one or more tasks.
<li>Specifying directives (functions that will be used from the build file).
</ul>
<h3 class="section" indent="1" id="base-plugin">BasePlugin</h3>
<p>
The main class of your plugin extends <code>BasePlugin</code> and implements its <code>apply()</code> method and <code>name</code> variable:
</p>
<pre>
public class ExamplePlugin : BasePlugin() {
override val name = "kobalt-example-plugin"
override fun apply(project: Project, context: KobaltContext) {
println("Applying plugin ${name} with project ${project}")
}
}
</pre>
<h3 class="section" indent="1" id="plugin-tasks">Plugin tasks</h3>
<p>
Next, you can declare tasks with the <code>@Task</code> annotation:
</p>
<pre>
@Task(name = "coverage", description = "Run coverage", runAfter = arrayOf("compile"))
public fun coverage(project: Project): TaskResult {
println("Running the coverage on project $project")
return TaskResult()
}
</pre>
<ul>
<li>Tasks return a <code>TaskResult</code> object, which can be initialized with <code>false</code> if the task didn't succeed for some reason.
<li>The name of the task is the same name that can be passed to the <code>kobaltw</code> command (e.g. <code>"./kobaltw coverage"</code>)
<li>The description is what is displayed with <code>"./kobaltw --tasks"</code>
<li><code>runAfter</code> and <code>runBefore</code> let you specify the dependencies of your task. In this example plug-in, we want to calculate the coverage of the project so it makes sense to run after the <code>"compile"</code> task.
</ul>
<h3 class="section" indent="1" id="plugin-directives">Directives</h3>
<p>
Finally, you need to define functions that can be used from the build file (directives). You are encouraged to use the <a href="https://confluence.jetbrains.com/display/Kotlin/Type-safe+Groovy-style+builders">Kotlin DSL approach</a> to expose these functions so that the build file syntax can remain consistent. Typically, these functions will update data that your tasks can then use to do their job.
</p>
<p>
These can be either straight functions or extension functions. For example, here is the <code>kotlinProject</code> directive:
<pre>
@Directive
public fun kotlinProject(init: KotlinProject.() -> Unit): KotlinProject {
val result = KotlinProject()
result.init()
return result
}
</pre>
<p>
This function returns a <code>KotlinProject</code> and the user can then override variables or invoke methods from this class in their build file:
</p>
<pre>
val kobalt = kotlinProject {
name = "kobalt"
group = "com.beust"
...
</pre>
<p>
Using an extension function to define a directive allows you to add new functions to Kobalt classes. For example, currently, a project can have <code>"dependencies"</code> and <code>"dependenciesTest"</code>. For a coverage plug-in, we would want to add a <code>"dependenciesCoverage"</code> section, which can be easily done by defining an extension function on <code>Project</code>:
</p>
<pre>
@Directive
public fun Project.dependenciesCoverage(ini: Dependencies.() -> Unit) : Dependencies {
val result = Dependencies()
result.init()
return result
}
</pre>
<p>
And we can now use:
</p>
<pre>
val p = kotlinProject {
dependenciesCoverage("com.example:foo:0.1")
}
if (experimental)
"com.squareup.okhttp:okhttp:2.4.0"
else
"com.squareup.okhttp:okhttp:2.5.0",
</pre>
<h2 class="section" id="sources">Sources and license</h2>

View file

@ -28,6 +28,10 @@ var content = [
{
url: "../ten-minutes/index.html",
title: "Ten minutes"
},
{
url: "../contributing/index.html",
title: "Contributing"
}
];

BIN
pics/auto-complete.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

BIN
pics/kobalt-jar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
pics/menu-sync.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
pics/source-root.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View file

@ -58,7 +58,7 @@
Kobalt plug-ins are usually made of several parts:
<ul>
<li><a href="#plugin-xml"><b>plugin.xml</b></a>. A file that describes all the components of your plug-in, such as contributors.</li>
<li><a href="#plugin-xml"><b>kobalt-plugin.xml</b></a>. A file that describes all the components 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>
@ -70,9 +70,9 @@
and keep reading.
</p>
<h2 class="section" id="plugin-xml">plugin.xml</h2>
<h2 class="section" id="kobalt-plugin-xml">kobalt-plugin.xml</h2>
<p>
The <code>plugin.xml</code> file (stored in <code>META-INF</code> in the jar file of your plug-in) is mandatory and describes all the components of your plug-in. At a minimum,
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 components of your plug-in. At a minimum,
this file will contain the name of your plug-in and the main plug-in class:
</p>
<pre>
@ -110,7 +110,7 @@
</p>
<p>In order to make things more concrete, let's take a look at
<a href=https://github.com/cbeust/kobalt/blob/master/src/main/resources/META-INF/plugin.xml">Kobalt's own <code>plugin.xml</code></a>
<a href=https://github.com/cbeust/kobalt/blob/master/src/main/resources/META-INF/kobalt-plugin.xml">Kobalt's own <code>kobalt-plugin.xml</code></a>
and go over it line by line.
</p>
<h4 class="section" indent="2" id="plugins">plugins (<a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/IPlugin.kt"><code>IPlugin</code>)</a></h4>
@ -265,7 +265,7 @@ public fun myConfig(project: Project, init: Info.() -> Unit) : Info {
</p>
<h2 class="section" id="tasks">Tasks</h2>
<p>
Tasks are provided by plug-ins and can be invoked from the command line, e.g. <code>./gradlew 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>
<h3 class="section" indent="1">Static tasks</h3>
<p>

View file

@ -9,7 +9,7 @@
<!-- Bootstrap core CSS -->
<link href="../bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="../css/kobalt.css" rel="stylesheet" />
<!-- Optional Bootstrap Theme -->
@ -69,10 +69,10 @@ val p = javaProject(wrapper) {
</pre>
<p>
Both these directives allow you to consider an object of type <code><a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/Project.kt">Project</code></a>.
Both these directives create an object of type <code><a href="https://github.com/cbeust/kobalt/blob/master/src/main/kotlin/com/beust/kobalt/api/Project.kt">Project</code></a>.
</p>
<h3 class="section" indent="1">Project</h3>
<h3 class="section" id="project" indent="1">Project</h3>
<p>
A <code>Project</code> has two mandatory attributes: <code>name</code> and <code>version</code>. If you are planning to deploy your project to a Maven repository, you also have to specify its <code>group</code> (e.g. <code>com.beust</code>) and <code>artifactId</code> (e.g. <code>kobalt</code>).
@ -92,7 +92,7 @@ A <code>Project</code> has two mandatory attributes: <code>name</code> and <code
<dd>The dependencies for your tests</dd>
</dl>
<h3 class="section" indent="1">Tasks</h3>
<h3 class="section" id="tasks" indent="1">Tasks</h3>
<p>
Once you have at least one project configured, the plug-in lets you invoke the following tasks:
<dl class="dl-horizontal">
@ -106,7 +106,103 @@ Once you have at least one project configured, the plug-in lets you invoke the f
<dd>Clean the project</dd>
</dl>
<h2 class="section" id="application">Application</h2>
<h3 class="section" id="variants" indent="1">Variants</h3>
<p>
Variants let you configure your project to generate different artifacts compiled from different sources depending on the <em>variant</em> you selected.
</p>
<div class="bs-callout bs-callout-warning">
<h4>Note</h4>
Kobalt's variant system is very similar to <a href="http://developer.android.com/tools/building/configuring-gradle.html">Android's build types</a>, so you should already be familiar with these concepts if you have built Android applications. The difference is that Kobalt supports variants in its core, so that all projects (not just Android's) can take advantage of it.
</div>
<p>
A variant is made of at least one of the following two components:
</p>
<ul>
<li>The product flavor.</li>
<li>The build type.</li>
</ul>
<p>
<strong>Product flavors</strong> usually contains different source files and different logic (e.g. a "free version" and a "pro version". <strong>Build types</strong> lead to different archives (e.g. "debug" and "release", with the "release" version being obfuscated). This effect is achieved by defining identical source files in different directories and then letting Kobalt build the correct one. Each product flavor and build type has a name which translates directory into a source directory. For example:
</p>
<pre>
productFlavor("free") {
}
buildType("release") {
}</pre>
<p>
With these variants defined, you can now add source files in the "<code>src/free/java</code>" and "<code>src/release/java</code>" directories (Kotlin is also supported):
</p>
<pre>
src/free/java/Product.java
src/release/java/Product.java</pre>
<p>
If you define at least one variant, new tasks get added to your build:
</p>
<pre>
$ ./kobaltw --tasks
===== java =====
compileFreeRelease
compileFreeDebug
===== packaging =====
assembleFreeRelease
assembleFreeDebug</pre>
<p>
For example, if you define two flavors, "pro" and "free", and two build types, "debug" and "release", four tasks will be added that combine these: "proDebug", "proRelease", "freeDebug" and "freeRelease". If you assemble any of these, an artifact named after that combination will be created, e.g. "kobalt-0.273-free-debug.jar".
</p>
<h3 class="section" id="build-config" indent="1">BuildConfig</h3>
<p>
If you defined at least one variant defined, a special file called <code>BuildConfig.java</code> (or
<code>BuildConfig.kt</code>) will be automatically generated.
</p>
<div class="bs-callout bs-callout-warning">
<h4>Note</h4>
You need to define <code>packageName</code> in your project in order for this file to be generated or
Kobalt will fail.
</div>
<p>
This class contains at least two fields defining the current variant:
</p>
<pre>
class BuildConfig {
companion object {
val PRODUCT_FLAVOR : String = "pro"
val BUILD_TYPE : String = "debug"
}
}</pre>
<p>
You can add your own custom fields to this file by calling the <code>buildConfig</code> directive
inside your
flavor:
</p>
<pre>
productFlavor("free") {
buildConfig {
field("aStringField", "String", "\"The free field\"")
field("anIntField", "Int", "42")
}
}</pre>
<p>
The generated file will then contain:
</p>
<pre>
class BuildConfig {
companion object {
val PRODUCT_FLAVOR : String = "free"
val BUILD_TYPE : String = "debug"
val aStringField : String = "The free field"
val anIntField : Int = 42
}
}</pre>
<p>
Take a look at the <a href=https://github.com/cbeust/kobalt-examples/tree/master/variants>variants example
project</a> to see an actual example using variants and <code>BuildConfig</code>.
</p>
<h2 class="section" id="application">Application</h2>
<p>
The "application" plug-in lets you run your application directly from <code>kobaltw</code>. You configure
it as follows:
@ -312,6 +408,45 @@ $ ./kobaltw uploadJcenter
All artifacts successfully uploaded
</pre>
<h2 class="section" id="dokka">Dokka</h2>
<p>
<a href="https://github.com/Kotlin/dokka">Dokka</a> is Kotlin's documentation tool. The Kobalt Dokka plug-in allows you to launch it and configure it as follows:
</p>
<pre>
import com.beust.kobalt.plugin.dokka.dokka
// ...
dokka {
outputFormat = "markdown"
sourceLinks {
dir = "src/main/kotlin"
url = "https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin"
urlSuffix = "#L"
}
}
</pre>
<p>
You can then generate your documentation by running the <code>dokka</code> task. Here is the full list of configuration parameters allowed:
</p>
<dl class="dl-horizontal">
<dt>samplesDir</dt>
<dd>The list of directories containing sample code (documentation for those directories is not generated but declarations from them can be referenced using the <code>@sample</code> tag).</dd>
<dt>includeDirs</dt>
<dd>The names of directories containing the documentation for the module and individual packages.</dd>
<dt>outputDir</dt>
<dd>The output directory where the documentation is generated.</dd>
<dt>outputFormat</dt>
<dd>The output format: <code>html</code>, <code>markdown</code>, <code>jekyll</code>,
or <code>javadoc</code>.</dd>
<dt>sourceLinks</dt>
<dd>The source link mappings.</dd>
<dt>moduleName</dt>
<dd>The name of the module being documented (used as the root directory of the generated documentation).</dd>
<dt>skip</dt>
<dd>If true, don't generate anything.</dd>
</dl>
</div>

View file

@ -84,7 +84,7 @@ val project = kotlinProject {
</pre>
<p>
Next, we need to create our <code>plugin.xml</code> file in the <code>src/main/resources/META-INF</code> directory.
Next, we need to create our <code>kobalt-plugin.xml</code> file in the <code>src/main/resources/META-INF</code> directory.
Once there, it will be automatically copied in the right place in our jar file:
</p>