Up to this point, you have been using the PDE Export Product wizard to publish and create end-user-deliverable versions of Toast. As Toast grows, and as it has more developers working on it and more configurations, there’s a pressing need for automated, reproducible, and accessible builds—release engineering.
Building modularized systems by hand is somewhat challenging and tedious. The compile-time classpath for any given bundle includes the code from all its prerequisites, in a very particular order and with quite a number of classpath access restrictions. Just computing the classpath and build order is hard. Mix in variations such as projects in the workspace, projects checked out from source control in the file system, or both, and the myriad of output packaging options, and you need help.
There are several build facilities out there, and the landscape is changing all the time. Maven, Ivy, Sigil, and many others all have benefits and drawbacks. Here we focus on the PDE Build infrastructure that comes with the Eclipse tool suite.
PDE Build does not claim to be a general build mechanism but rather a sophisticated OSGi bundle builder that has been in use for many years building Eclipse bundles. Because of that heritage it is well integrated into the Eclipse IDE and workflows.
This chapter dives into PDE Build and guides you through setting up an automated, reproducible build for the various parts of Toast. Here we cover
• Configuring and running a product build
• Running feature-based builds
• Building web archives (WARs)
• The different build.properties
files associated with building
• Customizing the build scripts
• Automatic version number qualification
So far, PDE’s Export wizards have insulated you from most of the details around building and packaging bundles. Unfortunately, those wizards are hard to automate, as you have to click around in a UI to launch a build. They are also hard to make repeatable, as they depend on the contents of the user’s workspace. Product teams and communities need release engineering builds that are automated and more rigorous. This is where PDE Build comes in.
You have actually been using PDE Build all along. It is the underlying infrastructure used for exporting bundles, features, and products from the workspace. It can also be used to perform release engineering builds of OSGi bundles.
PDE Build takes a product definition or a set of features and bundles and compiles and packages them according to the dependency information in their manifests and a set of control parameters. The output is an archive or directory structure that can be deployed directly or by using Java Network Launch Protocol (JNLP). As you saw in Section 14.5, “Exporting, Running, and Provisioning,” you can also export directly into p2 repositories for future provisioning.
At its heart, PDE Build is an Ant script generator. It takes in a collection of bundles and features, their manifests and build.properties
files, and generates a set of Ant build scripts. These scripts are run to produce a build. The export operations you have been doing throughout this book use PDE Build under the covers.
PDE Build is quite flexible. It can consume hybrid mixes of bundles and features that are prebuilt and those that remain to be built. Some may be included in the final output, and others may not. The output of a build can also vary from bundles in directories to p2 repositories and ZIP archives of JAR’d and signed bundles and features.
The build mechanism builds bundles and features, or cascades of the transitively included features and bundles starting at a root feature or product definition. Cross-platform building is also supported.
The main benefit of PDE Build is that it brings all this together into one relatively simple process. Developers express their normal runtime dependencies in manifest files and a mapping from development-time structure to runtime structure in the feature and bundle build.properties
files. PDE Build does the rest.
Key to this process is the automatic generation of the build scripts. Using the input manifests and build.properties
, PDE generates Ant scripts that copy files and compile code using a classpath derived by flattening the bundle dependency graph. The runtime classpath for a bundle is defined as a complex graph of bundle dependencies as described in its manifest file. The classes referenced at run-time are also needed at compile time, so the compile-time classpath is similarly complex. PDE Build uses the OSGi bundle resolution and wiring mechanisms to derive the classpath for each bundle being built.
build.properties
Before we get too far into PDE Build itself, let’s recap what you have used as a build process so far in the book. Since the PDE wizards have been doing most of the work, you have seen the build.properties
file only for the Toast bundles and features. This file is exposed on the Build page of the bundle and feature editors.
The role of the build.properties
file is to map development-time structures in a bundle’s project onto the structures described in the bundle’s manifest and needed at runtime. For example, by adding elements to the Binary Build section, you are stating that the deployable version of the bundle must include those elements.
The various PDE editors and wizards take care of managing binary build entries for most of the common cases. When you add images or other runtime resources to a bundle, you have to update the binary build information in the build.properties
to ensure that they are included in the build result.
The bundle editor’s Build page helps set up common build-related properties. To add more advanced properties, you have to edit the build.properties
file directly using the bundle editor’s build.properties page. When you set up automated builds, these advanced build properties become more relevant. Here we provide an example properties file and Table 20-1 for reference. See the PDE Help for a full list of build properties.
PDE uses this information, in combination with the bundle manifests, to generate a build.xml
script for each bundle that is then run during the build process.
You can opt out of the build script generation by supplying your own build.xml
and selecting Custom Build on the Build page of the bundle editor, as shown in Figure 20-1.
If you opt for a custom build.xml
, you take complete responsibility for implementing the build script that has all the right targets and that does all the right things. A better solution is to use custom callbacks; see Section 20.5.1, “Customizing the Build Scripts.”
To see how this works in practice, let’s set up a managed build process for the Toast Client from Chapter 14, “System Deployment with p2.” The client consists of the product definition, several Toast-related features and bundles, and various prebuilt bundles from the target platform.
• Start by creating a simple project for the build scripts using File > New... > Project > General > Project. Call it client.builder
.
• In the file system, navigate to your Eclipse IDE install and go to the org.eclipse.pde.build
bundle. For example, look in c:ideeclipsepluginsorg.eclipse.pde.build_3.5.1
if your IDE is installed in c:ide
.
• Copy both templatesheadless-builduild.properties
and scriptsproductBuildproductBuild.xml
to the client.builder
project. These are templates for the files used to control builds. In the subsequent sections, the templates are filled in and used to build the product.
The builder’s build.properties
file is quite different from the other build.properties
files you have seen so far. It contains key/value pairs that define the input parameters to the build itself. The productBuild.xml
is an Ant build file that controls the building of products. Having both files here allows you to override or add behavior to the build.
In addition to setting up the builder project, you must also ensure that the required binary dependencies are available. In particular, you need the right executable launcher for the platform you are building—PDE Build cannot assume it’s already present or know where it is.
The executables for all supported platforms are available in the executables feature. This feature is not intended to be installed; rather it contains native executables for a wide range of platforms. The easiest way to get the executables feature is to get the Eclipse delta pack. We saw the delta pack in Section 3.5, “Target Platform Setup.” Ensure that your target has the delta pack.
With the target setup, we have everything needed to run PDE Build. Unfortunately, as of this writing, PDE Build does not directly support the use of target definition files in its execution. This means that you must manually manage your binary prerequisites. To help with this we have included a simple tool, the Target Export wizard, that collects all of the bundles and features from the current target and places them in a single directory. You can then use the output of this tool in PDE Build. Run it now as follows:
• Select File > Export > Plug-in Development > Target definition to export the bundles and features that constitute the current target.
• Choose a directory for the Toast binary dependencies—for example, c: oast_prereqs
—and click Finish.
build.properties
Now that the build structure is in place, it needs to be customized to build our bundles. Following is a summary of the changes needed to the template build.properties
that was copied to the builder project. Some of the properties shown are needed later but are listed here to show the big picture. If a property is not listed here, it does not need to be changed. Of course, you should replace the file system locations appropriately.
Let’s look at each of these values and see how they affect the build. There are, of course, many more properties, but understanding these should give you an idea of how the build goes together and the level of control you have. The main information in build.properties
covers roughly seven areas of concern in the build process. Each of these is detailed in one of the following sections. They are presented roughly in decreasing order of interest; that is, you have to set up the values in the first section but may not have to change things in the last section.
These properties describe what you are building, the branding you want, and the shape of the output:
product
—The location of the product file that describes what is being built. The value takes the form /<id>/path/to/.product
, where <id>
is the ID of the feature or bundle project that contains the .product
file.
archivePrefix
—The specified prefix is added to the beginning of all paths in the output archive. This gives you control over the shape of your product when it is extracted on the user’s machine.
These properties allow you to control the working directories and names for the build output:
buildDirectory
—The absolute file system path where the build is executed. All build input is downloaded to this location, and all compilation and composition are done under this directory. You should keep this path reasonably short to avoid exceeding file system length limits. This is the only directory to which the builder needs to write permissions.
buildType
—An arbitrary string used to name the build output and identify the type of build. For example, organizations often have nightly (N) builds, maintenance (M) builds, integration (I) builds, and so on. There is no need to limit this value to a single character.
buildId
—The buildId
is used in composing the name of the output archives. Typically, the ID conveys some semantics, such as TestBuild
or CustomerX
, or a full date stamp, such as 20090701
.
buildLabel
—This is used in the naming of the output directories. The buildLabel
is typically a composition of buildType
and buildId
.
Most of the time you are building a set of bundles that sits on top of some base. Think of the base as the target for your workspace—it is all the bundles and features that you are not developing yourself. This may be the Equinox SDK, or it may be a whole product suite if you are an add-on developer. The properties here allow you to set where the base is, what’s inside, and how to get it if it is not present:
base
—The location of the product on which the build is based. This is used to determine if the base needs to be installed. If the directory exists, its contents are assumed to be complete. If it does not exist, the build system fetches the base and installs it at this location. In the example, we set the base to be the target platform that was exported using the Target Definition Export wizard.
baseLocation
—The location of the actual base install against which the bundles being built are to be compiled. This is the logical equivalent of the target used during development—all the bundles and features come from elsewhere. Note that this can be a full Eclipse install using link directories. This is specified separately from base
because different products have different internal structures. For example, the standard Eclipse downloads include an eclipse
directory in their structure. In these cases, the baseLocation
is just ${base}/eclipse
. In our case, we exported our target to c:/toast_prereqs
, so we can use that directly as both the base
and baseLocation
.
baseos
, basews
, basearch
—The os
, ws
, and arch
values for the base set of Equinox components in the install. Eclipse installations may support many platform configurations, so these settings are used to clarify the set of base bundles, fragments, and features to use. If there are several configurations in your base, pick one and assign the properties accordingly.
skipBase
—A marker property that, if set, indicates that fetching the base should be skipped.
pluginPath
—A list of locations where additional plug-ins and features can be found. Entries in this list are separated with the platform-specific separator.
This property helps control cross-platform building:
configs
—An ampersand-separated list of target machine configurations for which you want to build. Each configuration consists of an os
, ws
, arch
triple, such as win32
, win32
, x86
. The build process creates a separate output for each configuration. If the configuration is not set or is set to *
, *
, *
, the build is assumed to be platform-independent. In this example, we are building the Toast Client for Linux GTK and Windows.
The build process can automatically check out the source for the build from an SCM system. The location of the source is dictated by map files, which can themselves be checked out from an SCM system. The following properties let you bootstrap that process by setting basic locations and SCM tags to use:
mapsRepo
—The SCM repository that contains the map files needed for the build.
mapsRoot
—The path in the SCM mapsRepo
to the map files for the build.
mapsCheckoutTag
—The SCM tag used to check out the map files. The map files, in turn, control the SCM tags used for checking out the bundle and feature projects.
skipMaps
—A marker property that, if set, indicates that the map files are local and should not be checked out.
fetchTag
—A property used to override the SCM tags defined in the map files. For example, setting it to HEAD
is useful for doing nightly builds with CVS.
skipFetch
—A marker property that, if set, indicates that the source for the build is local and should not be checked out.
Depending on the way you wish to deploy your software, a p2 repository may be more convenient than platform-specific ZIP files. The following properties control the creation of a p2 repository containing the results of the build. The repositories can be used by others to provision the Toast Client shell and can also be used by PDE Build to build bundles intended to run on top of this product.
p2.gathering
—A marker property that, if set, indicates that all the build artifacts should be gathered into a p2 repository
p2.metadata.repo
—The location where the metadata repository is written if p2.gathering
is on
p2.artifact.repo
—The location where the artifact repository is written if p2.gathering
is on
p2.compress
—A marker property that, if set, indicates that the repositories should be compressed if p2.gathering
is on
The artifact and metadata repository properties should identify repository locations under a shared parent. Later, in Section 20.5.2, “Repositories and Additional Dependencies,” we may need to use the location of the parent as the repoBaseLocation
.
Of course, the build is primarily concerned with compiling Java code. The properties here allow you to define the compilation classpath as well as various arguments passed to the Java compiler:
bootclasspath
—The default boot classpath to use when compiling code. This should point to all the classes that are expected to be on the boot classpath when the product being built is run. The value is a semicolon-separated list of file system locations.
compilerArg
—A list of arguments to pass to the compiler.
Now that the builder is defined, you are ready to build the Toast Client. For most of this chapter we assume that you are working locally and already have the Toast code in your workspace. For simplicity, we also assume that you exported your target to c:/toast_prereqs
. With these assumptions, the builder does not need to access a server. To set this up, make sure that build.properties
has the following settings:
Because the bundles and features are not being checked out from CVS, you need to create the build directory by hand. In the following steps replace ${buildDirectory}
with the value from build.properties
, for example, ${user.home}/eclipse.build
:
• Create ${buildDirectory}
.
• Create ${buildDirectory}/plugins
.
• Create ${buildDirectory}/features
.
• Copy the required feature projects to the features directory and bundle projects to the plugins
directory. Figure 20-2 indicates which projects are needed and what the layout should look like in the end.
Now run the builder. The easiest way is to use a command prompt and change your working directory to the location of your builder. For example, if you have been following along, the builder files build.properties
and productBuild.xml
are in the client.builder
project in the workspace. Once there, run Eclipse’s AntRunner application using the following command line. The -buildfile
argument specifies the build file to run. Here we use productBuild.xml
. The -consolelog
argument ensures that you can see the output messages as the build progresses.
The build produces the structure shown in Figure 20-3 in the ${buildDirectory}/${buildLabel}
directory. In our example, the output goes in ${user.home}/eclipse.build/I.TestBuild
. This directory contains one archive per configuration that was built and a p2 repository. Each archive is a complete, ready-to-run Toast Client.
The compilelogs
directory contains the build logs for each bundle that was built. The various assembly and packaging scripts in the build directory are left over from the build and can be deleted. They are automatically deleted and regenerated each time the builder is run.
The repository
directory contains the p2 repository from which the Toast Client can be provisioned.
Now that you’ve seen the basics of how to build a system, here are some of the more common and useful customizations. These are not mandatory but are generally useful.
The templates
directory in the org.eclipse.pde.build
bundle has many useful script templates. You should copy these into your builder and customize them as needed. Table 20-2 presents an overview of the most relevant templates. For more information on customizing a build, see the Eclipse online Help documentation at http://help.eclipse.org and navigate to Plug-in Development Environment Guide > Tasks > PDE Build.
For the Toast Client we built before, we used the Target Export wizard to help create the base against which everything was compiled. However, this approach may not be ideal when configuring a build server. You may have various headless scripts and other facilities to get all the parts you need. If the dependencies end up in different directories, the pluginPath
and repoBaseLocation
properties can be used.
The pluginPath
property points to a separated list of additional locations in which PDE Build can look for prebuilt dependencies.
The repoBaseLocation
points to a single directory that may contain one or more p2 repositories in either ZIPped or extracted form. When this property is used, you must also specify the transformedRepoLocation
property and point it to a writable location on disk. PDE Build copies the contents of the base repositories and transforms them into a runnable form. All the bundles and features in the transformedRepoLocation
are then added to the pluginPath
.
PDE Build can also be configured to check out the source for the bundles and features being built from an SCM system, such as CVS or SVN. It uses the notion of map files to map feature and bundle IDs onto SCM repository locations and tags. This allows you to identify the top-level product or feature and let PDE Build figure out that you really mean “Check out a particular location in a particular repository using a particular SCM tag.” A map file contains a series of lines, each of which takes the following form:
If the path in the repository, the last element, is not specified, PDE Build assumes that the element to fetch is at the root of the repository and has the same name as the element. If your artifacts are in a different location in the repository, you must specify the complete path from the root of the repository to the directory containing the contents of the element, that is, the full path of the parent directory of the feature.xml
or plugin.xml
. Note that this path must not start with a “/
”.
In your ${buildDirectory}
, create a maps
directory, and in that directory create a toast.map
file that contains the following entries. Be sure to replace the repository information and the tag. You can use HEAD
for the tag if you only ever want to build from HEAD
. Note that in this case the qualifier is set to HEAD
as well—not very useful. See Section 20.5.6, “Qualifying Version Numbers,” for information on how to set the qualifier explicitly.
To save space, we have included only two features and one bundle in this map file. In practice, you must add an entry for each bundle and feature that needs to be built. All other elements are assumed to be in the base and do not need to be fetched or built.
Enable fetching by commenting out the skipFetch
property in build.properties
. Leave skipMaps=true
for now. Delete the plugins
and features
directories from the ${buildDirectory}
and run the build. Notice that the source listed in the map is checked out and built.
Sharing the map files in the SCM repository is the next logical step. There may be many map files, for example, each controlled by different teams. The simplest structure is to have a directory in the repository that holds the map files. Different teams then update their map files, and the build automatically picks up their changes.
During the build process, the getMapFiles
target in customTargets.xml
is called to download all the map files. The behavior of getMapFiles
is controlled by setting various properties in build.properties
, as shown here:
If skipMaps
is commented out, getMapFiles
checks out the contents of ${mapsRoot}
from ${mapsRepo}
using ${mapCheckoutTag}
and puts it into a maps
area in ${buildDirectory}
.
Set this up in the build.properties
, check your map files into a repository, and delete the entire contents of ${buildDirectory}
. Now, run the builder and watch that first the maps are checked out, then the features and bundles. Then, the build should continue as normal.
Deployed features are full of version numbers—included bundles and features are all identified by precise versions. Listing and managing these specific version numbers at development time is challenging, to say the least. If the version of a bundle changes, all referencing features have to be updated. This is cumbersome and error-prone.
To simplify the process, PDE Build includes support for automatically substituting version numbers during the build. You saw this in Chapter 14, “System Deployment with p2,” where included bundles and features were identified as version 0.0.0. The use of 0.0.0 tells PDE Build to substitute the version number of the bundle or feature used in the build. This eliminates the need to change the containing feature definition during development and ensures that the deployed version numbers are always correct. This is the default behavior of PDE Build.
You can lock in version numbers by setting them explicitly in the feature editor. For example, on the Bundles page of the feature editor, select Versions... in the Bundles and Fragments section. There you can select various policies for managing the version numbers. The options specified in the dialog apply to all bundles and fragments. If you want to lock down some bundle numbers but leave some to be assigned at build time, you have to use the feature.xml page and edit the file directly.
It is often handy to have output version numbers qualified by a build timestamp or other information. PDE Build supports a mechanism for optionally qualifying select bundle and feature version numbers during the build process.
Open the org.equinoxosgi.crust.shell
bundle’s editor and on the Overview page, set the bundle Version field to 1.0.0.qualifier
. Do the same for the org.equinoxosgi.toast.client.shell.feature
. During the build process, the qualifier
segment of the version is replaced with a user-selected value. This should be done for all bundles and features.
By default, the qualifier is derived from the context of the build. For example, if the build is based on checking out particular CVS tags using the map files described earlier, the qualifier for each bundle or feature is the CVS tag used to check out the source for the bundle. This way, the bundle’s full version number is based on its source.
If the build is not based on SCM tags or is using some sort of default tag—for example, the CVS HEAD
tag used in continuous integration builds—the qualifier for the version is the millisecond clock time when the bundle or feature was built.
You can force the value of the qualifier to be uniform across the build by setting the forceContextQualifier
property in the builder’s build.properties
, as shown in the next snippet. You should take care to use qualifier strings that are valid for file and folder names, as the qualifier shows up in the build output disk content. You should also take care to ensure that qualifiers are monotonically increasing so that successive builds have larger version numbers.
It is also possible to control the qualification of bundles and features on an individual basis by setting the qualifier
property in the relevant build.properties
, as shown here:
In product scenarios it is often required that various files be included in the root of the product distribution. This commonly includes various licenses and legal files and perhaps even a JRE. The PDE Build root files mechanism allows you to do this.
The root files mechanism is actually part of the feature build structure. Like bundles, features have their own build.properties
file that maps the development-time structure onto the runtime structure. This is where you describe the set of files to copy to the root of the final build output. The following snippet shows a typical feature’s build.properties
file. The bin.includes
property behaves exactly as described for bundles. The remainder of this section details the setup for root files. See the PDE Help for a full list of feature build properties.
The program launcher and related configuration files—for example, client.exe
, crust.ini
, and config.ini
—do appear at the root of an install but are not technically root files if you are building products. Products inherently identify and include the executable and these various configuration files, so they should not be specified again in a feature root file list.
The product definition and export wizards do not give you full control, however. For example, arbitrary root files such as licenses and legal files cannot be directly identified. These files must be enumerated in the build.properties
for a feature included in the product. The properties relevant to defining the root files are listed here:
root
—Files listed here are always copied to the root of the output. If a directory is listed, all files in that directory are copied to the root of the output.
root.<os.ws.arch>
—There should be one of these lines for each OS, window system, and processor architecture combination that has unique root files. For example, if you need to include compiled libraries or executables, you should identify them on the root lines for the appropriate configurations.
Each property value is a comma-separated list of files to copy to the root of the output. The files are identified using one of the following techniques:
• The contents of a directory structure are included by listing the parent directory itself. For example, root=rootfiles
copies the entire contents of the rootfiles
directory in the feature to the root of the build output. This is the most common setup seen in features.
• Individual files must be identified by prefixing their location with file:
. For example, the line
root.linux.gtk.x86=file:linux/special_executable
copies just the special_executable
file to the root. Note that the given path is relative to the feature, and the containing directory structure is not copied.
• Absolute paths can be specified by prefixing the location with absolute:
.
Executable files and libraries often need to have special permissions set when they are placed in the final archive so that when end users unpack the archives, the product is ready to run. You can control the permissions of the root files by defining a property of the form
root[.os.ws.arch].permissions.<perm_pattern>=<files>
The os.ws.arch
configuration identification is optional. The <perm_pattern>
is a UNIX file permissions triple, such as 755, which should be familiar to chmod
users. The value of the property is a comma-separated list of files to which the permissions should be applied. Ant patterns are supported for identifying files. Since permissions are applied once the files have been copied to their position in the root directory, all paths to permission files should be relative to the output root. Nonexistent files are silently skipped, and folders must be indicated with a trailing “/
”.
So far this chapter has focused on building stand-alone OSGi systems using Eclipse product definitions. The true utility of OSGi, however, is in the ability to extend a system with additional bundles. Here we show how to build and package some additional bundles, such as audio support, that can be optionally installed into the Toast Client.
In Chapter 14, “System Deployment with p2,” we defined a number of features to capture the different functional units that users might install into a Toast Client—audio, mapping, emergency, and so on. The discussion in the chapter showed you how to export these features independently and then provision them dynamically. Here we do basically the same thing but this time using PDE Build in a release engineering context.
To try this out, let’s set up a managed build process for the Toast Client’s audio feature. Overall the process is very much like the product builds done previously. As in Section 20.3, “Setting Up a Builder,” set up a build project primed with files from PDE itself:
• Start by creating a simple project called feature.builder
using File > New... > Project > General > Project and prime it with template build scripts from your IDE.
• In the file system, navigate to the install location of your Eclipse IDE and go to the org.eclipse.pde.build
. For example, look in c:ideeclipsepluginsorg.eclipse.pde.build_3.5.1
if your IDE is installed in c:ide
.
• From there, copy build.properties
and build.xml
from the templatesheadless-build
directory into your new builder project.
build.properties
The build.properties
file used to control the building of a top-level feature is similar to one used to build a product. The most significant properties are highlighted next, and we describe the differences between the product build.properties
and the file we need here.
Let’s look at each of these properties and how they affect the build. In particular, we focus on how these properties differ from those specified in a product build.
topLevelElementType
—Indicates the type of the top-level element being built—feature
or bundle
. This property is not used when building products.
topLevelElementID
—Indicates the ID of the feature or bundle to build.
repoBaseLocation
—This is the parent folder of the repository locations specified when building the client. The contents are used to compile and assemble the result.
transformedRepoLocation
—The contents of the repositories used may need to be converted into a runnable form. Runnable components are put in this location. Notice that baseLocation
contents may still be needed if the feature being built brings in functionality that is not yet part of the Toast Client.
p2.gathering
—Features that are built should be published to a repository from which clients can install the audio feature. In a feature build, unlike product builds, specifying the repository location in p2.metadata.repo
and p2.artifact.repo
is optional. If the location is not specified, the repository is in the build output location.
configs
—Since there is no platform-specific code in the audio feature, we can simply state that we are building for all platforms by setting the configs
property to *
, *
, *
.
Feature builds are invoked in the same way as the product build in Section 20.4, “Running the Builder”; that is, you must
• Create ${buildDirectory}
.
• Create ${buildDirectory}/plugins
.
• Create ${buildDirectory}/features
.
• Copy the required bundles and features to the plugins/
and features/
directories, as shown in Figure 20-5.
• Invoke org.eclipse.ant.core.antRunner
as shown here:
The build produces a structure as shown in Figure 20-6. The content goes in the ${buildDirectory}/${buildLabel}
directory or, in our example, in ${user.home}/audio_feature.build/I.TestBuild
. This directory contains an archive that consists of a fully built Toast audio feature. Because the p2.gathering
property was specified, the archive is also a p2 repository. Here we are interested only in the repository and can delete the archive.
In Chapter 19, “Server Side,” we saw how the back end could be packaged and delivered as a WAR. We set up a product definition and associated root files and then exported the product from the UI. The result was a .zip
file that can be used directly as a .war
after changing the file extension.
Since the Toast web application is described by a standard product, you can use the product build infrastructure discussed previously to build the WAR. All that is missing is the automatic renaming of the output .zip
file to be a .war
file. To set this up, you need to modify the builder to have a customTargets.xml
file and then have it run an Ant task in the postBuild
target:
• Copy the client.builder
project to make a war.builder
project.
• Follow the instructions in Section 20.5.1, “Customizing the Build Scripts,” to get the template customTargets.xml
into the new builder project.
• Modify the build.properties
in war.builder
to point to backend-war.product
and set the archivePrefix
property to WEB-INF
.
• Open customTargets.xml
and update the postBuild
target to move the build output to toast.war
:
• Finally, follow the steps in Section 20.4, “Running the Builder,” to copy the required features and run the build.
Here we covered the basics and got you started using PDE Build to compile and assemble the bundles, features, and products related to Toast. Regular and repeatable automated builds are a critical part of the development process. Without these, teams cannot integrate and have no idea if the system works.
PDE Build offers comprehensive tooling for building OSGi- and Eclipse-related artifacts. It is highly sophisticated and extensible. It is also very specialized. It is not a general-purpose build system. Since it is based on Ant, however, it can be integrated with one of the many build choreographing systems such as Hudson or CruiseControl. We strongly recommend setting up such a build process as early as possible in the life of your project.