Maven Make Orchestration Plugin

The Make Orchestration Plugin is used to invoke the various Make targets needed to run the build for a project that was originally setup to be built under that system. It consists of one abstract base class used to handle the functionality common among all of the Make-oriented mojos - namely execution of a shell command with arguments - along with several main concrete mojos and utility mojos to handle the main phases of a Make build. The main mojos are: validate-pom, configure, compile, test, make-clean, make-dist, and make-install. While the utility mojos are: chmod, chown, and autoreconf.

These mojos can be configured to run an alternate shell command instead of the default. They all can take command-line arguments that may embed one or more optional expressions for project paths. They all can signal that a specific file must change during the execution of that mojo. Finally, they each have a flag which can signal that the specified command must first have its execution bit set. This is handled by executing the utility chmod mojo as configured in the pom.xml.

Individually, the validate-pom mojo checks if the project property prefix is available in the current project before allowing it to continue building. The configure mojo can also specify a prefix for the built binaries. The compile mojo executes a Make-ish compile target to generate binaries from project source. The Make target for the test mojo can be specified as something different from its default of 'check'; it can specify a flag telling the mojo to ignore any test failures; and finally, it can specify a flag telling the mojo to skip testing entirely. Finally, the Make target for the make-install mojo can also specify a target other than the default of 'install'.

As an incidental implementation detail, these mojos use Ant tasks internally via the plexus Commandline and BouurneShell API's.

Expression Language for Path Options

The expression language supported for paths referenced inside command-line options is an extremely lightweight mechanism used to refer to either the Make DESTDIR for the project being built, or the systemPath of a direct dependency of the project. The syntax is accordingly lightweight and simple:

  • @destDir@ - substitute the autoconf/make DESTDIR in place of this expression. Useful for staged installs of software into a temp directory prior to the packaging phase.
  • @pathOf(groupId:artifactId)@ - lookup the dependency with the specified groupId and artifactId, and substitute its systemPath in place of this expression.

    NOTE: If the referenced dependency doesn't have a scope of system, the mojo will fail to execute citing the improperly scoped/referenced dependency in the command-line options.

Currently, simple regular expressions are used to make these substitutions.

Lifecycle Bindings

The mojos in this plugin are assigned to the following places inside the build lifecycle. Where applicable, notes on the relative ordering of the mojos to other mojos in the same phase are given.

  • valildate-pom - validate
  • configure - process-sources, after maven-patch-plugin:apply
  • compile - compile
  • test - test
  • make-install - test, before maven-rpm-plugin mojos. This will change to prepare-package phase in Maven 3.0

Why is make-install Bound to the Test Lifecycle Phase?

In adapting the Make build process to a Maven workflow, it became apparent that there was a bit of mismatch in the goals of the two systems. Maven's primary aim is to provide a portable package of software. The question of software installation is considered outside the scope of the Maven system. However, Make embraces the concept of installation, usually providing targets for installing the compiled binaries directly into the system at the specified location.

Using the initial goal of generating a RPM package from the Maven build result, it became apparent that the Make concept of installation went one step too far. Instead, the DESTDIR option was employed to redirect the installation of project binaries into a working directory, which will be used as a basis for creating a more portable package of the built software. In this scenario, the Make concept of installation actually fits more closely with a post-assembly of project binaries in preparation for packaging into RPM activity most closely related to the package phase. Therefore, the mojo was renamed to make-install from install to annotate this mismatch, and was subsequently prepended to the test phase, ahead of the rpm-harvesting mojos in the RPM lifecycle mapping for Make-oriented builds (discussed below).

The make-install phase will move to the prepare-package phase when Maven 3.0 is released.

Make-Oriented RPM Lifecycle Mapping

In addition to the aforementioned lifecycle bindings given by each mojo, this plugin defines a complete lifecycle mapping component for a project packaging called rpm. The defined mapping incorporates bindings to the following external Maven plugins:

  • maven-remote-source-plugin - Used to retrieve project sources from a URL outside the project. This will commonly be the case when orchestrating a Make build.
  • maven-patch-plugin - Along with externalized project sources, it will be common to require that a set of patches be applied prior to building. This goes along with the externalized nature of a Make-oriented build.
  • maven-rpm-plugin - Since this packaging is named rpm, it makes sense that we need the ability to harvest an RPM from the project binaries. Since the logic for harvesting an RPM is reusable outside the context of a Make-oriented build, it has been encapsulated in a separate plugin, and referenced here.
  • maven-install-plugin - Used to enable the default (jar-style) installation logic for placing the artifact in the local repository.
  • maven-deploy-plugin - Used to enable the default (jar-style) deployment logic for placing the artifact in the remote repository.

Why is the rpm Packaging Defined in a Make Orchestration Plugin?

The first use case we have for orchestrating Make builds involves the eventual goal of building a RPM package from the build result. However, its obvious that not all RPMs will be produced as a result of a Make-oriented build. The compromise, therefore, is to allow the POM to declare its packaging to be rpm and include the build extensions from this plugin - the maven-make-plugin in order to supply the build process with the lifecycle mapping for that packaging.

The net result of this separation is a definition of rpm packaging that is specific to Make-oriented builds. Other plugins may choose to redefine the process of building a RPM, which may not involve the use of Make. This use of the plugin-provided build extensions makes this sort of overloading elegant. In spite of the initial impression that this is a dangerous thing to overload, consider that no user will care how a project is built, only that it has produced a RPM package. However, to the project maintainers, the how question is at least as important as the end result of a RPM.

The Complete Make-Oriented RPM Lifecycle Mapping

  1. initialize. Multiple mojos; ordering is NOT important.
    1. get mojo in the maven-remote-source-plugin
    2. get mojo in the maven-patch-plugin
  2. process-sources. Multiple mojos; ordering is critical.
    1. apply mojo in the maven-patch-plugin
    2. configure mojo in this plugin (maven-make-plugin)
  3. compile. Uses the compile mojo in this plugin.
  4. test. Uses the test mojo in this plugin.
  5. package. Multiple mojos; ordering is critical.
    1. make-install mojo in this plugin
    2. generate-spec mojo in the maven-rpm-plugin
    3. build mojo in the maven-rpm-plugin
  6. install. Uses the install mojo in the maven-install-plugin.
  7. deploy. Uses the deploy mojo in the maven-deploy-plugin.

NOTE: Unlisted phases have empty bindings.