blob: a35cb45257990010f42e74bd3b5b75e84f0b126a [file] [log] [blame]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
<LINK REL="STYLESHEET" HREF="../book.css" CHARSET="ISO-8859-1" TYPE="text/css">
<TITLE>Incremental project builders</TITLE>
<link rel="stylesheet" type="text/css" HREF="../book.css">
</HEAD>
<BODY BGCOLOR="#ffffff">
<H2>
Incremental project builders</H2>
<P >
An <b>incremental project builder</b> is an object that manipulates the resources in a project in
a fashion that is defined by the builder itself.
Incremental project builders are often used to apply a
transformation on a resource to produce a resource or artifact of another kind.</P>
<P >
Plug-ins contribute incremental project builders to the platform in order to implement specialized resource transformations. For example, the Java development tooling (JDT)
plug-in that is provided
with the platform SDK defines an
incremental project builder that compiles a Java source file into a class file any time a file is added or modified in a
Java project and recompiles any other files affected by the change. </P>
<P >
The platform defines two types of builds:</P>
<ul>
<li>
A <b> full build </b> performs a build from scratch. It treats all resources in
the projects as if they have never been seen by the builder.</li>
<li>
An <b> incremental build</b> uses a &quot;last build state,&quot; maintained internally by the builder,
to do an optimized
build based on the changes since the last build.</li>
</ul>
<P >
Incremental builds are seeded with a resource change delta. The delta reflects the net effect of all resource changes since the builder last built the project.
This delta is similar to the one used inside resource change events.</P>
<P >
Builders are best understood by example. The Java development tooling (JDT) provides a Java compiler
which is driven by a Java incremental project builder to recompile files that
are affected by changes. When a full build is triggered, all of the
<b> .java</b> files in the project are compiled.&nbsp; Any compile problems encountered are added as problem markers on the affected
<b> .java</b> files. When an incremental build is triggered, the builder selectively recompiles
the added, changed, or otherwise affected
<b> .java</b> files that are described in the resource delta and updates the problem markers as necessary. Any
<b> .class</b> files or markers that are no longer appropriate are removed.</P>
<P >
Incremental building has obvious performance benefits for projects with hundreds or thousands of resources, most of which are unchanging at any given point in time.</P>
<P >
The technical challenge for incremental building is to determine exactly what needs to be rebuilt. For example, the
internal state maintained by the Java builder includes things like a dependency
graph and a list of compilation problems reported.&nbsp;
This information is used during an incremental build to identify which classes
need to be recompiled in response to a change in a Java resource. </P>
<P >
Although the basic structure for building is defined in the platform, the real work is done in your plug-in. Patterns for implementing complex incremental builders are beyond the scope of this discussion, since the implementation is dependent on the specific builder design. </P>
<H3>
Invoking a build</H3>
<P >
A builder can be invoked explicitly in one of the following ways:</P>
<ul>
<li>
<b>
IProject.build()</b> runs the build processing on the receiving project.</li>
<li>
<b>
IWorkspace.build()</b> runs the build processing on all open projects in the workspace.</li>
</ul>
<P >
In practice, the workbench user triggers a build by selecting the corresponding commands in the resource navigator menu.</P>
<P >
Incremental project builders are also invoked implicitly by the platform during an auto-build.
If enabled, auto-builds run whenever the workspace is changed.</P>
<H3>
Defining an incremental project builder</H3>
<P >
The <a href="../reference/extension-points/org_eclipse_core_resources_builders.html"> <b> org.eclipse.core.resources.builders</b></a> extension point is used to contribute an
incremental project builder to the platform. The following markup shows how the hypothetical plug-in
<b> com.example.builders</b> could contribute an
incremental project builder.</P>
<font color='#4444CC'><pre>
&lt;extension
id=&quot;mybuilder&quot; name=&quot;My Sample Builder&quot; point=&quot;org.eclipse.core.resources.builders&quot;&gt;
&lt;builder
&lt;run
<b>class=&quot;com.example.builders.BuilderExample&quot;</b>&gt;
&lt;parameter name=&quot;optimize&quot; value=&quot;true&quot; /&gt;
&lt;parameter name=&quot;comment&quot; value=&quot;Builder comment&quot; /&gt;
&lt;/run&gt;
&lt;/builder&gt;
&lt;/extension&gt;
</pre></font>
<P >
The <b> class</b> identified in the extension point must extend the platform class <b><a href="../reference/api/org/eclipse/core/resources/IncrementalProjectBuilder.html">IncrementalProjectBuilder</a></b>. </P>
<font color='#4444CC'><pre>
public class BuilderExample extends IncrementalProjectBuilder {
IProject[] build(int kind, Map args, IProgressMonitor monitor)
throws CoreException {
// add your build logic here
return null;
}
protected void startupOnInitialize() {
// add builder init logic here
}
}
</pre></font>
<P >
Build processing begins with the <b> build()</b> method, which includes information about the kind of build that has been requested,
<b>FULL_BUILD</b>, <b>INCREMENTAL_BUILD</b>, or
<b>AUTO_BUILD</b>. If an incremental build has been requested, a resource delta is provided to describe the changes in the project's resources since the last build. The following snippet further refines the
<b> build() </b> method.</P>
<font color='#4444CC'><pre>
protected IProject[] build(int kind, Map args, IProgressMonitor monitor
throws CoreException {
if (kind == IncrementalProjectBuilder.FULL_BUILD) {
fullBuild(monitor);
} else {
IResourceDelta delta = getDelta(getProject());
if (delta == null) {
fullBuild(monitor);
} else {
incrementalBuild(delta, monitor);
}
}
return null;
}
</pre></font>
<P>It sometimes happens that when building project &quot;X,&quot; a builder
needs information about changes in some other project &quot;Y.&quot;&nbsp; (For
example, if a Java class in X implements an interface provided in Y.)&nbsp;
While building X, a delta for Y is available by calling <b>getDelta(Y)</b>.&nbsp;
To ensure that the platform can provide such deltas, X's builder must have
declared the dependency between X and Y by returning an array containing Y from
a previous <b>build()</b> call.&nbsp; If a builder has
no dependencies, it can simply return null.&nbsp; See <b><a href="../reference/api/org/eclipse/core/resources/IncrementalProjectBuilder.html">IncrementalProjectBuilder</a></b>
for further information.</P>
<H4>
Full build</H4>
<P >
The logic required to process a full build request is specific to the plug-in. It may involve visiting every resource in the project (if the build was triggered for a project) or
even examining other projects if there are dependencies between projects.&nbsp; The following snippet
suggests how a full build might be implemented.</P>
<font color='#4444CC'><pre>
protected void fullBuild(final IProgressMonitor monitor) throws CoreException {
try {
getProject().accept(new MyBuildVisitor());
} catch (CoreException e) { }
}
</pre></font>
<P >
The build visitor would perform the build for the specific resource (and answer true to continue visiting all child resources).</P>
<font color='#4444CC'><pre>
class MyBuildVisitor implements IResourceVisitor {
public boolean visit(IResource res) {
//build the specified resource.
//return true to continue visiting children.
return true;
}
}
</pre></font>
<P >
The visit process continues until the full resource tree has been traveled.</P>
<H4>
Incremental build</H4>
<P >
When performing an incremental build, you work with a resource change delta instead of the
whole project.</P>
<font color='#4444CC'><pre>
protected void incrementalBuild(IResourceDelta delta,
IProgressMonitor monitor) throws CoreException {
// the visitor does the work.
delta.accept(new MyBuildDeltaVisitor());
}
</pre></font>
<P >
Note that for an incremental build, the build visitor works with a resource delta tree instead of a complete resource tree. </P>
<P >
The visit process continues until the complete resource delta tree has been traveled. The specific nature of changes
is similar to that described in
<a HREF="resAdv_events.htm#resAdv_events_listener" CLASS="XRef">Implementing a resource change listener</a>.&nbsp;
One important difference is that with incremental project builders, you are working with a resource delta based on a particular project, not the
entire workspace.</P>
<H3>
Associating an incremental project builder with a project</H3>
<P >
To make a builder available for a given project, it must be included in the build spec for the project. A project's build spec is a list of commands to run, in sequence, when the project is built. Each command names a single
incremental project builder. </P>
<P >
The following snippet adds a new builder as the first builder in the existing list of builders.</P>
<font color='#4444CC'><pre>
IProjectDescription desc = project.getDescription();
ICommand[] commands = desc.getBuildSpec();
boolean found = false;
for (int i = 0; i &lt; commands.length; ++i) {
if (commands[i].getBuilderName().equals(BUILDER_ID)) {
found = true;
break;
}
}
if (!found) {
//add builder to project
ICommand command = desc.newCommand();
command.setBuilderName(BUILDER_ID);
ICommand[] newCommands = new ICommand[commands.length + 1];
// Add it before other builders.
System.arraycopy(commands, 0, newCommands, 1, commands.length);
newCommands[0] = command;
desc.setBuildSpec(newCommands);
project.setDescription(desc, null);
}
</pre></font>
<P >
Configuring a project's builder is done just once, usually as the project is being created.</P>
<p><a href="../hglegal.htm"><img border="0" src="../ngibmcpy.gif" alt="Copyright IBM Corporation and others 2000, 2003." border="0" width="324" height="14"></a></p>
</BODY>
</HTML>