Skip to content

Commit

Permalink
Improve build
Browse files Browse the repository at this point in the history
  • Loading branch information
etiennestuder committed Apr 2, 2015
1 parent c3dc6d5 commit a2a2179
Show file tree
Hide file tree
Showing 18 changed files with 920 additions and 634 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ bin
*.iml
*.ipr
*.iws

screenshots
35 changes: 19 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ If you have already installed the plugin previously, you can update to the most

## Development Setup Instructions

This section describes the steps to setup Eclipse such that it can be used for development of Buildship.
This section describes the steps to set up Eclipse such that it can be used for development of Buildship.

### Setting up Eclipse

Expand All @@ -72,21 +72,25 @@ We use Eclipse
- as our development environment of Buildship and
- as our target platform against which we compile and run Buildship.

We use our internally-packaged Eclipse distribution, but the latest Eclipse for RCP Developers package should be fine, too.
We use a custom-packaged Eclipse distribution as our development environment, but the latest Eclipse for RCP Developers package should
be fine, too.

Proceed as following to get all the required software installed:
Our custom-packaged Eclipse distribution is available
at [http://dev1.gradle.org:8000/eclipse/distro](http://dev1.gradle.org:8000/eclipse/distro).

1. Download the Eclipse distribution matching your OS from the http://dev1.gradle.org:8000/eclipse/distro/ site.
1. Untar the downloaded distribution and start Eclipse.
1. Install the latest version of Buildship from the e44 update site listed above.
If you do not use our custom-packaged Eclipse distribution, we suggest to still import our project preferences which are available
at [http://dev1.gradle.org:8000/eclipse/config/formatter.epf](http://dev1.gradle.org:8000/eclipse/config/formatter.epf).

We plan to soon release an [Oomph](https://wiki.eclipse.org/Eclipse_Oomph_Installer) setup model to provide a convenient
way to set up the local development environment.

### Getting the source code

The project and its source code is hosted on GitHub: `https://github.com/gradleware/buildship`.
The project and its source code is hosted on GitHub: `https://github.com/eclipse/buildship`.

Apply the following command to get a clone of the source code:

git clone [email protected]:gradleware/buildship.git
git clone [email protected]:eclipse/buildship.git

#### Committers

Expand Down Expand Up @@ -120,10 +124,10 @@ can then press _Finish_.
### Setting the target platform

After importing all the projects into Eclipse, there will be some build errors due to code references to missing
plugins. To add these missing plugins to Eclipse, open the _tooling-e44.target_ file (or the one matching your
Eclipse version) located in the project root folder and click _Set as Target Platform_ in the top-right corner. This
will fix all compilation issues. Note, that it might take a while as it will download a whole SDK for the specified
version of Eclipse.
plugins. To add these missing plugins to Eclipse, open the _tooling-e45.target_ file (or the one matching your
desired target platform version) located in the project root folder and click _Set as Target Platform_
in the top-right corner. This will fix all compilation issues. Note that this might take a while since the entire
SDK for the specified Eclipse version will be downloaded.

### Running the tests inside of Eclipse

Expand Down Expand Up @@ -152,13 +156,12 @@ To have full build ids in the name of the generated jars and in the manifest fil

./gradlew build -Pbuild.invoker=ci

The default Eclipse version to use as the target platform is defined in the root project's _build.gradle_ file. To override the
Eclipse version to use as the target platform, set the `eclipse.version` accordingly:
The available target platforms are defined in the root project's _build.gradle_ file, under the _eclipseBuild_ node.
By default, the build runs against target platform version _45_. To build against a different target platform version,
you can set the `eclipse.version` Gradle project property:

./gradlew build -Peclipse.version=44

The possible values for `eclipse.version` are: 36, 37, 42, 43, 44, and 45.

### Continuous Integration

Buildship is continuously built on our [Continuous Integration Server](https://builds.gradle.org/project.html?projectId=Tooling_Buildship&tab=projectOverview).
Expand Down
427 changes: 262 additions & 165 deletions buildSrc/src/main/groovy/eclipsebuild/BuildDefinitionPlugin.groovy

Large diffs are not rendered by default.

206 changes: 105 additions & 101 deletions buildSrc/src/main/groovy/eclipsebuild/BundlePlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -10,47 +10,53 @@
*/

package eclipsebuild
import java.util.List;

import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.Copy;
import org.mozilla.classfile.SuperBlock;

import aQute.bnd.maven.support.Maven;
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.tasks.Copy

/**
* Gradle plugin for building Eclipse bundles
* <p>
* Applies the java plugin by default.
* <p>
* Makes the os, ws and arch variables available for the project (via project.ext) for building against platform-dependent
* dependencies; for example <pre> compile "eclipse:org.eclipse.swt.${project.ext.ws}.${project.ext.os}.${project.ext.arch}:+"</pre>
* <p>
* To make the compilation work, the compileJava task depends on the establishment of the target platform.
* <p>
* To construct the output jar just like Eclipse PDE the plugin loads the contents of the <code>build.properties</code>
* file and brings it in sync with the jar's content.
* <p>
* The <it>updateLibs</it> assigns takes all project dependencies defined in the <code>bundled</code> scope, and copies
* them (including transitives) into the lib folder and modifies the bundle manifest to export all packages from the libraries.
* Gradle plug-in for building Eclipse bundles.
* <p/>
* It adds extra functionality to the existing Java plug-in to resolve dependencies and Eclipse
* bundles much like with PDE-based build.
* <p/>
* It makes OSGi-related variables like os, ws and arch available for the project (via project.ext)
* for building against platform-dependent dependencies. An example dependency on SWT:
* <pre>
* compile "eclipse:org.eclipse.swt.${project.ext.ws}.${project.ext.os}.${project.ext.arch}:+"
* </pre>
* To construct the output jar the plugin loads the contents of the <code>build.properties</code>
* file and sync it with the jar's content.
* <p/>
* The plug-in defines a new scope called {@code bundled}. If dependency is defined with this
* scope and the {@code updateLibs} task is called, the dependency (and its transitives) is (1)
* copied into the lib folder (2) added to the project descriptors and (3) referenced from the
* bundle manifest file.
*/
class BundlePlugin implements Plugin<Project> {

static final String TASK_NAME_UPDATE_LIBS = 'updateLibs'
static final String TASK_NAME_COPY_LIBS = 'copyLibs'
static final String TASK_NAME_UPDATE_MANIFEST = 'updateManifest'

@Override
public void apply(Project project) {
configureProject(project)
addUpdateLibsTasks(project)

addTaskCopyLibs(project)
addTaskUpdateManifest(project)
}

void configureProject(Project project) {
static void configureProject(Project project) {
// apply the java plugin
project.plugins.apply('java')
project.plugins.apply(JavaPlugin)

// make new variables for the build.gradle file e.g. for platform-dependent dependencies
project.ext.ECLIPSE_OS = Constants.os;
project.ext.ECLIPSE_WS = Constants.ws;
project.ext.ECLIPSE_ARCH = Constants.arch;
project.ext.ECLIPSE_OS = Constants.os
project.ext.ECLIPSE_WS = Constants.ws
project.ext.ECLIPSE_ARCH = Constants.arch
project.ext.ECLIPSE_VERSION = Config.on(project).eclipseVersion

// add new configuration scope
Expand All @@ -59,31 +65,24 @@ class BundlePlugin implements Plugin<Project> {
project.configurations { compile.extendsFrom bundled }

// make the most basic task depend on the target platform assembling
project.tasks.compileJava.dependsOn ":installTargetPlatform"
project.tasks.compileJava.dependsOn ":${BuildDefinitionPlugin.TASK_NAME_INSTALL_TARGET_PLATFORM}"

// Make sure the manifest ifile exists
// make sure the required descriptors exist
assert project.file('build.properties').exists()
assert project.file('META-INF/MANIFEST.MF').exists()

// Use the same MANIFEST.MF file as it is in the project except the Bundle-Version
// use the same MANIFEST.MF file as it is in the project except the Bundle-Version
PluginUtils.updatePluginManifest(project)

// Parse build.properties and sync it with output jar
PluginUtils.syncJarContentWithBuildProperties(project)

// assemble task does't change anything outside the buildDir folder
project.tasks.assemble.outputs.dir project.buildDir
// parse build.properties and sync it with output jar
PluginUtils.configurePluginJarInput(project)
}

void addUpdateLibsTasks(Project project) {
project.task('updateLibs', dependsOn: ['copyLibs', 'updateManifest']){
group = Constants.gradleTaskGroupName
description = '''Copies the bundled dependencies into the project's lib folder and updates the manifest file'''
}

project.task('copyLibs', dependsOn: [
static void addTaskCopyLibs(Project project) {
project.task(TASK_NAME_COPY_LIBS, dependsOn: [
project.configurations.bundled,
project.configurations.bundledSource,
":installTargetPlatform"
":${BuildDefinitionPlugin.TASK_NAME_INSTALL_TARGET_PLATFORM}"
], type: Copy) {
group = Constants.gradleTaskGroupName
description = 'Copies the bundled dependencies into the lib folder'
Expand All @@ -105,76 +104,81 @@ class BundlePlugin implements Plugin<Project> {
from project.configurations.bundled
from project.configurations.bundledSource
}
}

project.task('updateManifest', dependsOn: project.configurations.bundled) {
static void addTaskUpdateManifest(Project project) {
project.task(TASK_NAME_UPDATE_MANIFEST, dependsOn: project.configurations.bundled) {
group = Constants.gradleTaskGroupName
description = 'Updates the manifest file with all the dependencies of the Tooling API'
doLast { updateManifest(project) }
}
}

// check the existence of the manifest file in configuration-time
assert project.file('META-INF/MANIFEST.MF').exists()

doLast {
// don't write anything if there is no bundled dependency
if (project.configurations.bundled.dependencies.isEmpty()) {
return
}

File manifest = project.file('META-INF/MANIFEST.MF')
List<String> lines = manifest.readLines()
int i = 0;

manifest.withPrintWriter { out ->
// copy file upto line with 'Bundle-ClassPath: .'
while (i < lines.size() && !lines[i].startsWith('Bundle-ClassPath: .,')) {
out.println(lines[i])
i++
}
static void updateManifest(Project project) {
// don't write anything if there is no bundled dependency
if (project.configurations.bundled.dependencies.isEmpty()) {
return
}

out.print 'Bundle-ClassPath: .,'

// add a sorted list of jar file names under the Bundle-Classpath section
boolean comma = false
def bundledConfig = project.configurations.bundled as List
bundledConfig.sort { it.name }.each { File jarFile ->
if (jarFile.toString().endsWith('.jar')) {
if (comma) {
out.println(',')
} else {
out.println()
}
String name = jarFile.getName()
out.print(" lib/$name")
comma = true
}
}
out.println()
File manifest = project.file('META-INF/MANIFEST.MF')
project.logger.info("Update project manifest '${manifest.absolutePath}'")
List<String> lines = manifest.readLines()
int i = 0

// skip lines up to 'Export-Package: '
while (i < lines.size() && !lines[i].startsWith('Export-Package: ')) {
i++
}
manifest.withPrintWriter { out ->
// copy file upto line with 'Bundle-ClassPath: .'
while (i < lines.size() && !lines[i].startsWith('Bundle-ClassPath: .,')) {
out.println(lines[i])
i++
}

// copy the remaining lines
while (i < lines.size()) {
out.println lines[i]
i++
out.print 'Bundle-ClassPath: .,'

// add a sorted list of jar file names under the Bundle-Classpath section
boolean comma = false
def bundledConfig = project.configurations.bundled as List
bundledConfig.sort { it.name }.each { File jarFile ->
if (jarFile.toString().endsWith('.jar')) {
if (comma) {
out.println(',')
} else {
out.println()
}
String name = jarFile.getName()
out.print(" lib/$name")
comma = true
}
}
out.println()

// update the .classpath file
def classpathFile = project.file('.classpath')
def classpathXml = new XmlParser().parse(classpathFile)
// delete all nodes pointing to the lib folder
classpathXml.findAll { it.name().equals('classpathentry') && it.@path.startsWith('lib/') }.each { classpathXml.remove(it) }
// re-create the deleted nodes with the 'sourcepath' attribute
project.configurations.bundled.sort { it.name }.each { File jarFile ->
def name = jarFile.getName()
def nameWithoutExtension = name.substring(0, name.lastIndexOf('.'))
new Node(classpathXml, 'classpathentry', ['exported' : 'true', 'kind' : 'lib', 'path' : "lib/$name", 'sourcepath' : "lib/${nameWithoutExtension}-sources.jar"])
}
new XmlNodePrinter(new PrintWriter(new FileWriter(classpathFile))).print(classpathXml)
// skip lines up to 'Export-Package: '
while (i < lines.size() && !lines[i].startsWith('Export-Package: ')) {
i++
}

// copy the remaining lines
while (i < lines.size()) {
out.println lines[i]
i++
}
}
project.logger.debug("Manifest content:\n${manifest.text}")


// update the .classpath file
def classpathFile = project.file('.classpath')
project.logger.info("Update .classpath file '${classpathFile.absolutePath}'")
def classpathXml = new XmlParser().parse(classpathFile)
// delete all nodes pointing to the lib folder
classpathXml.findAll { it.name().equals('classpathentry') && it.@path.startsWith('lib/') }.each { classpathXml.remove(it) }
// re-create the deleted nodes with the 'sourcepath' attribute
project.configurations.bundled.sort { it.name }.each { File jarFile ->
def name = jarFile.getName()
def nameWithoutExtension = name.substring(0, name.lastIndexOf('.'))
new Node(classpathXml, 'classpathentry', ['exported' : 'true', 'kind' : 'lib', 'path' : "lib/$name", 'sourcepath' : "lib/${nameWithoutExtension}-sources.jar"])
}
new XmlNodePrinter(new PrintWriter(new FileWriter(classpathFile))).print(classpathXml)
project.logger.debug(".classpath content:\n${classpathFile.text}")
}

}
Loading

0 comments on commit a2a2179

Please sign in to comment.