A multi-module project that demonstrates features of the iwant
build system
After cloning this repository, cd to it and type your first wish to shell (remember that tab is your friend - oh, and you are expected to have bash and other standard unix tools in your path, as well as a Java SDK):
as-iwant-demo-developer/with/bash/iwant/help.sh
Note how you don't need to install or configure anything. A small amount of bootstrapping code will ensure you have the correct version of iwant
serving your build wishes.
As this is the first wish, it forces the iwant
bootstrapper to bootstrap iwant
and generate more wishes. Use tab again and issue the next wish:
as-iwant-demo-developer/with/bash/iwant/side-effect/eclipse-settings/effective
Note that we have to start with an exceptional way of using iwant
: we wished for a side-effect, a mutation to the system. Most of the time we wish for targets instead, but since Eclipse dictates the location of its settings files and owns them, we have to be imperative here.
Now that you have the Eclipse settings generated, you can import the projects to Eclipse. (Don't copy them to the workspace, just import.)
Modules iwant-demo-wsdef
and iwant-demo-wsdefdef
define the build, and the rest of the modules are production modules. Your first entrypoint to the build is IwantDemoWorkspaceModuleProvider.java
. (Use shift-ctrl-T to open it with Eclipse.) It defines the actual build module. The entrypoint to the build, defined as string here, is IwantDemoWorkspaceFactory.java
. From that you can navigate your way with ctrl-click.
Note how you can study how the build is defined by utilizing the Java type system and Eclipse navigation features instead of reading documentation and following loosely typed references and conventions.
When you have finished your initial study of the code you can make your next wish to get a test coverage report and pipe it to a browser:
as-iwant-demo-developer/with/bash/iwant/target/jacoco-report-all/as-path | xargs -r chrome
Or, if you prefer fancier use of xargs
, open the browser directly to the correct file:
as-iwant-demo-developer/with/bash/iwant/target/jacoco-report-all/as-path | xargs -r -Ixxx chrome xxx/index.html
Note how you didn't tell iwant
to run tests. In fact, if you run the command again, it wont' run them because you didn't change the code coverage by touching anything. Even the methods of IwantDemoWorkspace.java
that define the target, jacocoReportAll
and jacocoReport
, don't mention anything imperative like running tests but just define nouns related to the report you are after.
Also note how all progress output of refreshing a target is printed to stderr, not stdout, so the output of the wish, the path of the target, is the only thing that goes to the next process in the pipeline - xargs and chrome in this case.
To see the contents of the application cli distribution and to run it issue the following commands:
as-iwant-demo-developer/with/bash/iwant/target/cli-distro/as-path | xargs -r find
as-iwant-demo-developer/with/bash/iwant/target/cli-distro/as-path && as-iwant-demo-developer/.i-cached/target/cli-distro/run.sh
Note how easily CliDistro.java
includes all runtime dependencies of the application in the lib directory of the distribution.
Follow the error message of the application. For example, to print the first 4 prime numbers, type:
as-iwant-demo-developer/with/bash/iwant/target/cli-distro/as-path && as-iwant-demo-developer/.i-cached/target/cli-distro/run.sh --primes 4
The cli demonstrates usage of a generated javabean, GeneratedBean
, with the following command:
as-iwant-demo-developer/with/bash/iwant/target/cli-distro/as-path && as-iwant-demo-developer/.i-cached/target/cli-distro/run.sh --generatedbean "new value"
See how IwantDemoModules.java
defines generatedJavaBeansJava.jar
as a jar of classes compiled from java files generated by a custom target, GeneratedJavaBean.java
.
The code generator JavaBeanGenerator.java
is defined in a module that is not only built by the build system but also used by it during build. That's why it is defined very early, by IwantDemoWorkspaceModuleProvider.java
and included as a dependency to the iwant-demo-wsdef
module that defines most of the build.
Note how GeneratedJavaBean.java
declares the ingredients it needs for generating the java files. It not only declares the source file (generated-javabeans/beans.txt
) it consumes as an ingredient, but also its own java file and the classpath location that contains the code generator, JavaBeanGenerator.class
.
This makes sure the target will be refreshed if you touch any of the declared ingredients.
Try this by how touching generated-javabeans/beans.txt
, GeneratedJavaBean.java
or JavaBeanGenerator.java
causes a refresh of the target generatedJavaBeansJava.classes
when requesting for example for target cli-distro
.
Also note how the target is not refreshed if none of its ingredients has changed.
You can get a findbugs report by running:
as-iwant-demo-developer/with/bash/iwant/target/findbugs-report/as-path | xargs -r -Ixxx chrome xxx/findbugs-report/findbugs-report.html
The project demonstrates customizing the code style policy for its modules in
IwantDemoModules.java
method commonSettings
. The policies are defined in IwantDemoCodeStyles.java
.
The module iwant-demo-sloppy-legacy
uses exceptional code formatting and style settings.
Note how easily you can enforce a zero tolerance of warnings even in a project with below-standard legacy code by relaxing opinionated default settings where needed.
joulu unsigned-byte
is a simple depencencyless module. The method jouluUnsignedByte
of IwantDemoModules.java
defines it as a java binary module compiled from sources downloaded from github.
To use it from the cli run
as-iwant-demo-developer/with/bash/iwant/target/cli-distro/as-path && as-iwant-demo-developer/.i-cached/target/cli-distro/run.sh -u 3
Note how easy and natural it is to reuse code that hasn't even been "officially" published to a (maven) binary repository.
Anteru compares several build systems in his Build systems blog. He hosts the example project at bitbucket.
To be honest iwant
is heavy for very simple (non-java) projects, because it requires some bootstrapping overhead (the wsdefdef and wsdef java modules) and, in practice, a heavy IDE for editing the build.
But as AnteruBuildSystemsExample.java
demonstrates, the actual target definitions of Anteru's example project are reasonably dry. (And the bigger the project, the drier it can be made with the power of Java and object oriented programming.)
To try out the example executable run
as-iwant-demo-developer/with/bash/iwant/target/anteru-build-systems-example/as-path && as-iwant-demo-developer/.i-cached/target/anteru-build-systems-example/run.sh
Note how the target is refreshed even when you make a trivial change to any shell command that defines a target. Even GNU make that otherwise is a very fine example of a declarative lazy build system falls for cache invalidation here.
Also note how easy it is to not only define parts of the application but also a full distribution directory with a run script.
There is a lot more you can do with iwant
. Why don't you tell me what you want demonstrated next? Maybe challenge iwant
with something that is especially difficult for other build systems. Or especially easy for them, for comparison. Or fork this project and do it yourself! Don't hesitate to ask for help.
- Ville Oikarinen (firstname at lastname dot org)
(author of iwant
)