Chapter 20. Release Engineering

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

20.1 What Is PDE Build?

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.

Product Files

Product definitions were introduced in Chapter 9, “Packaging.” They are build-time configuration files that describe the bundles and features that constitute a running OSGi system. In addition to the bundles and features, product files can be used to specify launch configurations, program and VM arguments, and branding information.

For more information, see the online Eclipse Help at http://help.eclipse.org. Navigate to Plug-in Development Environment Guide > Concepts > Product.

20.2 Bundle 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.

20.2.1 Control Properties

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.

image

Table 20-1 Bundle Build Properties

image

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.

20.2.2 Using Custom Build Scripts

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.

Figure 20-1 Custom Build selection

image

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.”

20.3 Setting Up a Builder

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.

20.3.1 Tweaking the Target for PDE 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.

20.3.2 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.

image

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.

20.3.2.1 Product and Packaging Control

These properties describe what you are building, the branding you want, and the shape of the output:

productThe 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.

archivePrefixThe 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.

20.3.2.2 Build Naming and Locating

These properties allow you to control the working directories and names for the build output:

buildDirectoryThe 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.

buildTypeAn 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.

buildIdThe 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.

buildLabelThis is used in the naming of the output directories. The buildLabel is typically a composition of buildType and buildId.

20.3.2.3 Base Identification and Location

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:

baseThe 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.

baseLocationThe 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, basearchThe 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.

skipBaseA marker property that, if set, indicates that fetching the base should be skipped.

pluginPathA list of locations where additional plug-ins and features can be found. Entries in this list are separated with the platform-specific separator.

20.3.2.4 Cross-Platform Building

This property helps control cross-platform building:

configsAn 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.

20.3.2.5 SCM Access Control

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:

mapsRepoThe SCM repository that contains the map files needed for the build.

mapsRootThe path in the SCM mapsRepo to the map files for the build.

mapsCheckoutTagThe 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.

skipMapsA marker property that, if set, indicates that the map files are local and should not be checked out.

fetchTagA 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.

skipFetchA marker property that, if set, indicates that the source for the build is local and should not be checked out.

20.3.2.6 Publishing a Product Build to a p2 Repository

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.gatheringA marker property that, if set, indicates that all the build artifacts should be gathered into a p2 repository

p2.metadata.repoThe location where the metadata repository is written if p2.gathering is on

p2.artifact.repoThe location where the artifact repository is written if p2.gathering is on

p2.compressA 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.

20.3.2.7 Java Class Libraries and Compiler Control

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:

bootclasspathThe 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.

compilerArgA list of arguments to pass to the compiler.

Managing Ant Properties

PDE Build makes heavy use of Ant constructs and in particular Ant properties. The properties listed here are treated as normal Ant properties, so ${variable} substitution is supported. Also, values such as the bootclasspath are passed directly to the associated Ant task.

The so-called marker properties are ones that are simply set or not set. The value is irrelevant and not checked. For simplicity, we tend to show the value as true, but setting the value to false does not unset the property.

It is often convenient to use build.properties to set up defaults and then override these values for a particular build. This is done by setting properties from the command line using the -D<prop>=<value> VM argument syntax.

For more advanced settings, see the Ant documentation at http://ant.apache.org.

20.4 Running the Builder

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:

image

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.

Figure 20-2 Build layout

image

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.

image

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.

Figure 20-3 Build output

image

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.

Debugging the Build

Builds are notoriously hard to get right. Spelling mistakes, commented lines, and typos all contribute to builders that just do not work. The Eclipse IDE includes comprehensive support both for authoring Ant files and for debugging Ant scripts. There are a few quirks to setting this up for PDE Build, so the steps are detailed here.

You must have the root build script in your workspace. If you have been following along, you should have the product build script in your workspace. If not, you can import it:

• Use the Import > Plug-ins and Fragments wizard to import the org.eclipse.pde.build bundle.

• In the wizard, set the Bundle Location to your IDE location (e.g., c:ideeclipse) and choose Import As > Binary projects.

• Click Next, select the org.eclipse.pde.build bundle, and Add it to the list.

• Click Finish.

Now you have to set up a launch configuration to run PDE Build’s build.xml, the root of the build mechanism:

• Navigate to org.eclipse.pde.build/scripts/productBuild/productBuild.xml and use the context menu’s Debug As > Ant Build... to open the Ant launch configuration dialog.

• On the JRE page, select Run in the same JRE as the workspace.

• On the Properties page, uncheck Use global properties... and use Add Property... to add a property called builder, as shown in Figure 20-4.

Figure 20-4 Ant builder properties

image

• Click Debug and run the build.

Everything should work as before. Now you can open PDE’s Ant scripts, such as productBuild.xml, and add breakpoints by double-clicking in the left margin or using the Toggle Breakpoint context menu. Debug the build again. When the breakpoint is hit, you can inspect Ant properties and step over and into Ant statements.

20.5 Tweaking the Build

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.

20.5.1 Customizing the Build Scripts

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.

Table 20-1 PDE Build Templates

image

20.5.2 Repositories and Additional Dependencies

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.

20.5.3 Fetching from an SCM System

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:

image

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.

image

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.

Fetching the Product File

In the case of a product build, there is a bit of a catch-22 situation. The .product file drives the list of features and bundles to be built. This file is typically in a bundle or feature project in the SCM, but the map file mechanism does not have a way of indicating which project or where it is. Since the .product file drives the fetch phase of the build and the fetch phase cannot fetch it, it must be checked out explicitly.

This can be accomplished using a custom build step early on in the build, for example, by adding the following Ant instructions to the postSetup target in customTargets.xml:

image

See Section 20.5.1, “Customizing the Build Scripts,” for more information on the customTargets.xml file.

Integrating with SCM Systems

Source code repositories and SCM systems figure heavily in the overall release engineering process. PDE Build supports several tools such as CVS and SVN. CVS is supported out of the box, whereas SVN requires the installation of some additional bundles. In both cases standard command-line SCM tools are used to fetch content—PDE Build does not assume the existence of an Eclipse workspace, so the normal Eclipse SCM clients cannot be used.

If you are on a UNIX machine, chances are you have CVS and SVN already installed—type cvs or svn at the command line to check. If not, consult your OS installer instructions.

On Windows you have to manually download and install the clients. You can get CVS from http://cvsnt.org and SVN from http://tigris.org or http://polarion.com.

SVN users need to augment the standard PDE Build infrastructure with the ability to read SVN-oriented map file entries and use SVN for fetching. See the instructions on the PDE wiki at http://wiki.eclipse.org/PDEBuild.

20.5.4 Fetching the Maps

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:

image

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.

20.5.5 Auto-substitution of Version Numbers

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.

20.5.6 Qualifying Version Numbers

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.

image

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:

image

20.5.7 Identifying and Placing Root Files

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.

image

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:

rootFiles 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 “/”.

20.6 Building Add-on Features

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.

20.6.1 Setting Up a Feature Builder

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.

20.6.2 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.

image

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.

topLevelElementTypeIndicates the type of the top-level element being built—feature or bundle. This property is not used when building products.

topLevelElementIDIndicates the ID of the feature or bundle to build.

repoBaseLocationThis is the parent folder of the repository locations specified when building the client. The contents are used to compile and assemble the result.

transformedRepoLocationThe 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.gatheringFeatures 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.

configsSince 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 *, *, *.

20.6.3 Running the Feature Build

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.

Figure 20-5 Feature build layout

image

• Invoke org.eclipse.ant.core.antRunner as shown here:

image

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.

Figure 20-6 Feature build output

image

20.7 Building WARs

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:

image

• Finally, follow the steps in Section 20.4, “Running the Builder,” to copy the required features and run the build.

20.8 Summary

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.130.24