Home -> Professional -> Component Build
Maven is a very good, powerful way to build a Java product, that can handle a product divided into projects. Unfortunately, not all products are able to use Maven, for whatever reason (company policies, difficult learning curve, etc.). Maven also has a few requirements that don't always fit the natural shape of a product. Ant, on the other hand, is a simpler, more widely accepted way to build a Java product. It works at a lower level than Maven, and so often requires more work to achieve the same results.
When a codebase becomes larger, it becomes more and more painful to build the whole product. It would be helpful to have a "component" build, in Ant, that allows the developers to work on one part of the codebase while allowing the rest of the codebase to be nearly ignored. Once the source has been partitioned into the appropriate chunks, how do we get Ant to build the right way?
A component build should:
One directory structure that supports some of the goals is:
branch/ -- The top of the build system; a convenient place to check out
files from the source code repository.branch/topbuild -- The "top build" component, containing the build scripts
and supporting files (libraries, configurations, etc.) for the entire product.branch/component -- The top of each component, containing
source, build scripts, supporting files, and all else needed for a single component.branch/component/src -- The source directory. Everything that
becomes part of the distributed product from this component belongs somewhere under here,
so that this is the only directory that needs to be checked to see if changes have been
made that force a rebuild. Subdirectories are named for the type of source.branch/component/src/java -- The java source directory.
All java files that qualify as source have their path start under this directory. For a
product whose files live in packages "com.mycompany...", there would be a "com".
directory under this one.branch/component/src/web -- The web source directory.
All files used directly to build a web archive (.war, .ear, etc.), such as HTML, JSP,
manifests, etc., belong here, in a directory structure that mirrors the structure
within the archive.branch/component/src/conf -- The configuration source
directory. All configuration files that end up in the distributed product belong somewhere
under here.branch/component/test -- The test directory. Everything that
is used to run automated tests belongs under this directory. The subdirectories are named
for the type of test artifact contained.branch/component/test/java -- The java test directory.
This directory contains all unit tests and other tests that are used with this component.branch/component/test/data -- The test data directory.
This directory contains all files needed by unit tests or other tests.branch/component/test/conf -- The test configuration directory.
This directory contains all configuration files needed by unit tests or other tests.branch/component/build -- The build directory. When compiled,
linked, assembled, or otherwise transformed into some intermediate form, the results are
stored here in an appropriate directory structure. The build's "clean" target deletes this
directory, so nothing permanent should be here.branch/component/testbuild -- The test build directory.
When compiled, linked, assembled, or otherwise transformed into usable form, the test
executables are stored here in an appropriate directory structure. Tests are run using
this directory or specific subdirectories as classpath nodes, or using .jar files in
this directory on the classpath. The build's "clean" target deletes this directory, so
nothing permanent should be here.branch/component/dist -- The distribution directory. The
component's distributable artifacts go here. They should be few in number, generally.
This directory is the only directory from which other components may satisfy their
dependencies. The build's "clean" target deletes this directory, so nothing permanent
should be here.The rest of this discussion assumes such a directory structure. While there are other perfectly good directory structures, this one is assumed so that the following arguments don't have to digress into handling all the other possibilities. It should be easy enough to modify the component build ideas to work with other directory structures (and if it isn't, that's probably a defect in the directory structure).
There are two types of build script in this design: Top-level build, and component
build. The top-level build gets its own "component" directory
(branch/topbuild), and each component gets its own eponymous
component directory.
Also, note that the examples here are simplified build scripts. The output is simple .jar files, instead of .war or .ear files, directories of Java classes, combined java and native code, or whatever else may be needed. The marker file and check file approach to preventing unnecessary build steps has no impact on, and is not affected by, the type of build output. Neither are they affected if the build is enhanced with library dependency checking, other types of tests, style checking, static code analysis, continuous integration, etc.
The master build file, the one that should be invoked by default when
the user types "ant" at the command line. Thus, it should be included as
branch/topbuild/build.xml.
| build.xml |
Anyone who tries to use this build script, or very attentive readers, may
have noticed that it imports another file, header.xml. It is found
in the same directory as the master build file, as
branch/topbuild/build.xml.
| header.xml |
The topbuild directory also contains some Ant scripts that are used in the
component builds. This one defines the standard classpaths used for building
the source, and for building and running unit tests. It is found at
branch/topbuild/classpath.xml.
| classpath.xml |
The dependency.xml script is included in any component build
script whose component depends on one or more other components. It establishes
several targets that are needed to allow the component to act as a dependency
and to use others as dependencies. It is found at
branch/topbuild/dependency.xml.
| dependency.xml |
The nodependency.xml script is included in any component build
script whose component does not depend on any other components. It establishes
several targets that are needed to allow the component to act as a dependency.
It is found at
branch/topbuild/nodependency.xml.
| nodependency.xml |
Components with no dependencies have a build file that does not look for
dependencies. The build script is placed at the top of the component's
tree, named
branch/component/build.xml.
| build.xml (no dependencies) |
Components with dependencies have a build file that can trigger a build for the
dependencies as well. The build script is placed at the top of the component's
tree, named
branch/component/build.xml.
| build.xml (dependencies) |
Copyright © 2004-2010, Leif Bennett. All rights reserved.