A multi-module project that demonstrates features of the
iwant build system
Quick start: Studying the code with Eclipse
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):
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.
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.)
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.
Studying test coverage (aka "running the tests")
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,
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.
(Building and) running the application
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
Using code to build during build: code generation
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"
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.
Cache validity of a custom target
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,
This makes sure the target will be refreshed if you touch any of the declared ingredients.
Try this by how touching
JavaBeanGenerator.java causes a refresh of the target
generatedJavaBeansJava.classes when requesting for example for target
Also note how the target is not refreshed if none of its ingredients has changed.
Static code analysis with findbugs
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
Code style and formatting
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.
Simple module compiled from sources 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.
Case: gcc, static and dynamic linking, code generation (Anteru's build-systems example)
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.
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)