Monthly Archives: November 2012

Reduce disk access in Windows 7

Although I’m not a big user of Windows, sometimes I use it to test my software and products. When switching to Windows Vista and Windows 7 I’ve always noticed a huge use of the disk.

Here are some tricks I’ve used to reduce such use

First of all make sure to disable indexing for the whole hard disk (checkbox “Allow files on this drive…”)

Then stop the Windows Search service and…

make sure it is disabled (right click and the Properties)

Finally, make sure that you have no scheduled defragmentation (you can check this by pressing “Defragment now…”

This should reduce disk access, hopefully :)

any comment and suggestion is more than welcome!

 

Be Sociable, Share!

Mirror Eclipse repositories with p2.mirror Ant task

Inspired by this nice blog post, I decided it was time to try to mirror some Eclipse repositories to

  • speed up my builds that depend on target platforms
  • insulate myself from outside servers
  • be able to build also without an Internet connection
  • reduce network traffic :)

To do this I’m using p2 ant tasks for mirroring repositories.

When mirroring eclipse repositories, my main idea is to keep the path structure of the original repository URL. For instance, if you are using something like

http://download.eclipse.org/releases/juno

the mirror should differ only for the base url, e.g., something like

/home/myhome/eclipsemirror/releases/juno

This is useful if the p2 repositories you use for materializing your target platform are parametrized with respect to the base URL. For instance, I’m using Buckminster to materialize my target platforms (see also this post), and in my RMAP files I have something like

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0">

  <rm:property key="eclipse.download" value="http://download.eclipse.org"/>

  <rm:property key="xtext.p2.repository" 
        value="${eclipse.download}/modeling/tmf/xtext/updates/composite/releases/"/>
  <rm:property key="eclipse.target.platform" 
        value="${eclipse.download}/releases/juno"/>
  <rm:property key="swtbot.repository" 
        value="${eclipse.download}/technology/swtbot/helios/dev-build/update-site"/>
  <rm:property key="orbit.repository" 
        value="${eclipse.download}/tools/orbit/downloads/drops/R20120526062928/repository/"/>

...

</rm:rmap>

You see that the URLs are parametrized over the property eclipse.download (which defaults to http://download.eclipse.org). If I mirror those repositories keeping the same structure

then, switching to my local mirror for target materialization it’s just a matter of passing for the property eclipse.download the URL of my local directory, e.g., file:/home/bettini/eclipsemirror, without even changing my RMAP files.

So let’s start mirroring! We need to define an Ant script for the p2 antRunner.

For instance, for mirroring the whole orbit repository (with that particular drops version) we create this script, let’s call it mirror-orbit.xml:

<project name="Create Mirror" default="create-mirror" basedir=".">

  <target name="create-mirror">
    <p2.mirror source="http://download.eclipse.org/tools/orbit/downloads/drops/R20120526062928/repository">
      <destination location="${target.dir}/tools/orbit/downloads/drops/R20120526062928/repository"  />
    </p2.mirror>
  </target>

</project>

Note that we keep in the target dir the same path structure of the original repository.

Since these Ant tasks need to be run via the Eclipse antRunner application, you need a full installation of Eclipse on the machine that will run the task. And you run this task with a command line like the following

/path/to/eclipse -noSplash \
   -application org.eclipse.ant.core.antRunner \
   -buildfile mirror-orbit.xml \
   -Dtarget.dir=$HOME/eclipsemirror

Of course you can choose any target dir; the idea is however to always use the same target dir so that all repositories will be mirrored in that path.

Mirroring an entire repository might not always be the case, especially for Juno main release repository, which is quite huge. But you can specify in the Ant task the installable units you’re interested in; then, the p2 task will only mirror those installable units (and all its dependencies). For instance,

<project name="Create Mirror" default="create-mirror" basedir=".">
  <target name="create-mirror">
    <p2.mirror source="http://download.eclipse.org/releases/juno">
      <destination location="${target.dir}/releases/juno"  />
      <iu id="org.eclipse.sdk.feature.group" />
      <iu id="org.eclipse.equinox.executable.feature.group" />
      <iu id="org.eclipse.emf.sdk.feature.group" />
      <iu id="org.eclipse.emf.query.sdk.feature.group" />
      <iu id="org.eclipse.net4j.sdk.feature.group" />
      <iu id="org.eclipse.net4j.db.feature.group" />
      <iu id="org.eclipse.emf.cdo.sdk.feature.group" />
      <iu id="org.eclipse.draw2d.sdk.feature.group" />
    </p2.mirror>
  </target>

</project>

This task will mirror all the features that should let you define a target platform for RCP development with EMF and CDO.

NOTE: if you try to mirror org.eclipse.platform.sdk from the releases/juno repository, you will see that it will actually mirror the whole repository! (see also this forum post).

If you get some warnings during the mirror about unsolvable dependencies, you can ignore them: basically those dependencies are in a different repositories, and probably you will mirror those repositories too later.

Of course you can use several p2.mirror elements in the same Ant task. For example, this is the one we use in Emf Components, to have a mirror for our target platform: it also mirrors Swtbot and Xtext SDKs:

<project name="Create Mirror" default="create-mirror" basedir=".">

  <target name="create-mirror">

    <p2.mirror source="http://download.eclipse.org/releases/juno">
      <destination location="${target.dir}/releases/juno"  />
      <iu id="org.eclipse.sdk.feature.group" />
      <iu id="org.eclipse.equinox.executable.feature.group" />
      <iu id="org.eclipse.emf.sdk.feature.group" />
      <iu id="org.eclipse.emf.query.sdk.feature.group" />
      <iu id="org.eclipse.net4j.sdk.feature.group" />
      <iu id="org.eclipse.net4j.db.feature.group" />
      <iu id="org.eclipse.emf.cdo.sdk.feature.group" />
      <iu id="org.eclipse.draw2d.sdk.feature.group" />
    </p2.mirror>

    <p2.mirror source="http://download.eclipse.org/tools/orbit/downloads/drops/R20120526062928/repository">
      <destination location="${target.dir}/tools/orbit/downloads/drops/R20120526062928/repository"  />
    </p2.mirror>

    <p2.mirror source="http://download.eclipse.org/modeling/tmf/xtext/updates/composite/releases">
      <destination location="${target.dir}/modeling/tmf/xtext/updates/composite/releases"  />
      <iu id="org.eclipse.xtext.sdk.feature.group" />
      <iu id="org.eclipse.xtend.sdk.feature.group" />
      <iu id="org.eclipse.xpand.sdk.feature.group" />
    </p2.mirror>

    <p2.mirror source="http://download.eclipse.org/technology/swtbot/helios/dev-build/update-site">
      <destination location="${target.dir}/technology/swtbot/helios/dev-build/update-site"  />
      <iu id="org.eclipse.swtbot.eclipse.feature.group" />
      <iu id="org.eclipse.swtbot.ide.feature.group" />
      <iu id="org.eclipse.swtbot.eclipse.test.junit4.feature.group" />
      <iu id="org.eclipse.swtbot.forms.feature.group" />
      <iu id="org.eclipse.swtbot.feature.group" />
    </p2.mirror>

  </target>

</project>

Final warning: it might take some time for the mirror task to complete (usually hours depending on your connection and download.eclipse.org load) and it will also take some hard disk space (for the above mirror it takes about 2 Gb).

You may have to experiment a bit to get all the features you need in the mirror; for instance, I didn’t know about the draw2d above, but I had to add it since during target materialization that feature was requested by some other feature. If you’re lost about that, you can always mirror the whole thing ;)

There’s also a follow up post showing how to run this ant task from Eclipse!

But then your builds will be faster :)

Be Sociable, Share!

Building Xtext projects with Buckminster

One of the new cool features which came with Xtext 2.3.0 is a wizard which generates all the artifacts to build your Xtext DSL project with Buckminster; this will allow you to easily build your Xtext project p2 site and also to build your project and its tests headlessly (e.g., from the command line, and, more importantly from within a continuous integration system like Jenkins).

This new feature was not advertised much, nor documented, so I decided to write a tutorial about that, also with the permission of the developer of this feature Dennis Hübner.

In this tutorial I will show how to

  • create the p2 repository from the IDE
  • build your project (and run the tests) headlessly from the command line (through ant)
  • build your project (and run the tests) headlessly in a continuous integration system like Jenkins

In the end, I will also try to describe/explain all the Buckminster files that the wizard created for you, so that one can customize them.

The sources used in this tutorial can be found at

https://github.com/LorenzoBettini/Xtext-Buckminster-Example

Create an Xtext project

So, first of all, let’s create a simple Xtext hello project; for this example I will use the following settings:

  • project name: org.xtext.example.hellobuck
  • name: org.xtext.example.hellobuck.HelloBuck
  • extension: greetings
  • check “Create SDK feature project”

and then, of course, we generate Xtext artifacts.

The DSL is basically the standard Greetings DSL; in this case, I’m using the JvmModelInferrer to generate Java classes from “Hello” specifications. Indeed, the DSL itself is not important in this tutorial. I’ve also added two Junit tests in the corresponding org.xtext.example.hellobuck.tests project:

Note the org.xtext.example.hellobuck.tests.launch Launch configuration that Xtext created for you (which basically runs all the Junit tests in this project. We will see how this will be used later.

Use the Xtext Build with Buckminster Wizard

Now we can use the Xtext wizard “Build with Buckminster”: New => Other => Xtext => Continuous Integration => Build with Buckminster:

You will have to specify the sdk feature of your Xtext project (that has been created by the Xtext new project wizard); the releng and site projects will have predefined names. For the Buckminster installation directory you have 3 choices:

  • if you have already an headless installation of Buckminster in your system you can specify the path;
  • you can install it using the link in the dialog
  • you can leave that path empty and specify it later in the build.ant generated file (or pass it on the command line when invoking ant)

In any case, specifying the headless Buckminster installation path is only useful if you intend to build your projects headlessly with ant (it is not requested for building in the IDE, nor if you plan to build it with Jenkins by setting job using the Buckminster Jenkins plugin, as we will see later).

Before pressing Finish, we also want to specify the tests to launch during the headless build, so we press the button Add and we select the launch configuration in the .tests project which the Xtext wizard created for us.

If you want to build an existing Xtext project and you do not have that launch configuration, all you need to do is to simply create a new plain Junit launch configuration from the IDE, for instance, to run your existing Junit test suite, and save it in the .tests project yourself. You can also configure the headless build to run tests later on.

When the wizard finishes, you will end up with two additional projects

  • org.xtext.example.hellobuck.buckminster with all the Buckminster (CQUERY and RMAP, build.ant, etc.) files to build your project headlessly;
  • org.xtext.example.hellobuck.site which is a feature project to create the p2 repository for your Xtext project.

Build the p2 repository from the IDE

Although the .buckminster project created by the wizard is thought to be used in an headless environment, the .site project is useful also to build the p2 repository from the IDE itself! Indeed, if you created an old style update site, you could build the update site from the IDE itself. But if you switched to the new category.xml format, then building the corresponding p2 repository from the IDE is not straightforward.

If you want to run Buckminster from Eclipse, you first need to install it in the IDE of course, by using this repository: http://download.eclipse.org/tools/buckminster/updates-4.2

Before creating the p2 repository, you may want to tweak some Buckminster properties, for instance, you may want to create a buckminster.properties file in the .buckminster project (or in the .site project) like the following

# Where all the output should go
buckminster.output.root=${user.home}/tmp/hellobuck/build
# Where the temp files should go
buckminster.temp.root=${user.home}/tmp/hellobuck
# How .qualifier in versions should be replaced
qualifier.replacement.*=generator:lastRevision

target.os=*
target.ws=*
target.arch=*

so that Buckminster will generate all its artifacts in the tmp/hellobuck directory of your home folder.

We now right click on the .site project, and select Buckminster => Invoke Action… , we select site.p2 action, and optionally refer to the buckminster.properties file

When the action finishes, you will file the p2.site in the directory $HOME/tmp/hellobuck/build/org.xtext.example.hellobuck.site_1.0.0-eclipse.feature/site.p2/

Build with ant

The wizard created for us, in the .buckminster project a build.ant file that we can use to build the project, run the tests, and create the p2 repository with ant

Note that this file has the location of your Buckminster headless installation path hardcoded (recall the wizard we used before for creating Buckminster projects); if that is not correct, you can still pass this information to ant when invoking it

ant -Dbuckminster.home=<PATH> -f build.ant

This ant script will build your project in the directory buildroot which will be created in the directory where all your projects are located (e.g., in the workspace or in another path); in particular it will

  1. materialize the target platform for your project (the first time you run it), and this requires an Internet connection and might take some time
  2. build your projects
  3. run the Junit tests
  4. build the p2 site repository

This should be the output (where WORKSPACE is actually the location of your projects):

Buildfile: WORKSPACE/org.xtext.example.hellobuck.buckminster/build.ant
cleanup:
buckminster:
     [echo] IMPORTANT: Populating an empty target platform may took over 10 minutes.
     [exec] INFO:  setpref 'targetPlatformPath=WORKSPACE/buildroot/target.platform'
     [exec] WARN:  Target platform directory 'WORKSPACE/buildroot/target.platform' does not exist and will be created
     [exec] INFO:  resolve 'WORKSPACE/org.xtext.example.hellobuck.buckminster/projects-platform.cquery'
     [exec] INFO:  Resetting target platform Directory WORKSPACE/buildroot/target.platform
     [exec] INFO:  Import complete.
     [exec] INFO:  resolve 'WORKSPACE/org.xtext.example.hellobuck.buckminster/project.cquery'
     [exec] INFO:  Import complete.
     [exec] INFO:  build
     [exec] INFO:  junit '-l' 'org.xtext.example.hellobuck.tests/org.xtext.example.hellobuck.tests.launch' '--flatXML' '--output' 'WORKSPACE/buildroot/buckminster.output/test.results/org.xtext.example.hellobuck.tests.launch.xml'
     [exec] INFO:  Starting test session org.xtext.example.hellobuck.tests
     [exec] INFO:  Running test org.xtext.example.hellobuck.tests.HelloBuckCompilerTest.testGeneratedJava...
     [exec] INFO:    ...OK [0.877s]
     [exec] INFO:  Running test org.xtext.example.hellobuck.tests.HelloBuckCompilerTest.compareGeneratedJava...
     [exec] INFO:    ...OK [0.189s]
     [exec] INFO:  Running test org.xtext.example.hellobuck.tests.HelloBuckParserTest.testParsingAndValidation...
     [exec] INFO:    ...OK [0.096s]
     [exec] INFO:  Tests finished.
     [exec] INFO:  Elapsed time: 1.164 seconds.
     [exec] INFO:  Total number of tests executed: 3
     [exec] INFO:  Successful tests: 3
     [exec] INFO:  Failed tests: 0
     [exec] INFO:  Errors: 0
     [exec] INFO:  Ignored tests: 0
     [exec] INFO:  Overall status: OK
     [exec] INFO:  perform 'org.xtext.example.hellobuck.site#site.p2'
     [exec] INFO:  [start org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#eclipse.build]
     [exec] INFO:  [end org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#eclipse.build]
     [exec] INFO:  [start org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#bundle.jar]
     [exec] INFO:  [end org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#bundle.jar]
     [exec] INFO:  [start org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#eclipse.build]
     [exec] INFO:  [end org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#eclipse.build]
     [exec] INFO:  [start org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#bundle.jar]
     [exec] INFO:  [end org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#bundle.jar]
     [exec] INFO:  [start org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#feature.jar]
     [exec] INFO:  [end org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#feature.jar]
     [exec] INFO:  [start org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#source.manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#source.manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#source.bundle.jar]
     [exec] INFO:  [end org.xtext.example.hellobuck:osgi.bundle$1.0.0.qualifier#source.bundle.jar]
     [exec] INFO:  [start org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#source.manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#source.manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#source.bundle.jar]
     [exec] INFO:  [end org.xtext.example.hellobuck.ui:osgi.bundle$1.0.0.qualifier#source.bundle.jar]
     [exec] INFO:  [start org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#source.manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#source.manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#source.feature.jar]
     [exec] INFO:  [end org.xtext.example.hellobuck.sdk:eclipse.feature$1.0.0.qualifier#source.feature.jar]
     [exec] INFO:  [start org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#copy.subfeatures]
     [exec] INFO:  [end org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#copy.subfeatures]
     [exec] INFO:  [start org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#copy.plugins]
     [exec] INFO:  [end org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#copy.plugins]
     [exec] INFO:  [start org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#manifest]
     [exec] INFO:  [end org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#manifest]
     [exec] INFO:  [start org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#site.p2]
     [exec] INFO:  [end org.xtext.example.hellobuck.site:eclipse.feature$1.0.0.qualifier#site.p2]
     [echo]  
     [echo] Updatesite output in: WORKSPACE/buildroot/buckminster.output/org.xtext.example.hellobuck.site_*-eclipse.feature/site.p2/
BUILD SUCCESSFUL
Total time: 3 minutes 39 seconds

It will also tell you where you can find the generated p2 site.

IMPORTANT: there’s a bug in the currently generated build.ant file, which prevent you from building with ant in Windows; until the fixed version of the wizard is released, you need to make sure that the build.ant has the right contents, as in this example source.

Build with Jenkins

To build your Xtext project in Jenkins you can either create a Job which uses ant and the build.ant script, or create a Job which uses the Buckminster Jenkins plugin (I’ve also blogged about that). I will detail both ways. Both jobs have in common the access to the git repository

A Job using ant

This requires that you configured an ant installation in your Jenkins, and that you already have a working version of Buckminster headless in Jenkins; you need to specify them in the ant build step configuration (the screeshots, of course, refer to the paths and values for my Jenkins installation):

then, we configure post build actions to archive both the artifacts (the p2 repository) and the Junit results:

A job using Buckminster plugin

To configure a Buckminster build step, we prepare a text file in the .buckminster projects with the Buckminster commands to execute (we take inspiration from the commands.txt file that the wizard created), we call it jenkins-commands.txt:

resolve 'org.xtext.example.hellobuck.buckminster/projects-platform.cquery'
resolve 'org.xtext.example.hellobuck.buckminster/project.cquery'
clean
build
perform -D target.os=* -D target.ws=* -D target.arch=* org.xtext.example.hellobuck.site#buckminster.clean
perform -D target.os=* -D target.ws=* -D target.arch=* org.xtext.example.hellobuck.site#site.p2
junit -l 'org.xtext.example.hellobuck.tests/org.xtext.example.hellobuck.tests.launch' --stderr -o 'tests_output/org.xtext.example.hellobuck.tests.launch.xml'

Then we configure a build step (this relies on a Buckminster installation that we have already configured in Jenkins), note that we refer to the jenkins-commands.txt we created above (an alternative would be to copy the commands directly in the text area “Commands”):

To configure the post build actions, since we used different output paths, we have to specify them accordingly (in particular, we have not used the output directory buildroot, thus the default will be used):

Details and Customization

It may be interesting to learn more about the files that the Xtext Buckminster wizard generated for you (at least, I personally found instructive to look at them, and learned something about Buckminster :) most of which I described in another post of this blog). The details might also help you if you need to customize the generated files.

The .buckminster project contains a Component Specification (CSPEC), buckminster.cspec, which looks like

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0" name="org.xtext.example.hellobuck.buckminster" componentType="buckminster" version="1.0.0">
    <cs:dependencies>
        <cs:dependency name="org.eclipse.platform" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.xtext.sdk" componentType="eclipse.feature"/>
    </cs:dependencies>
</cs:cspec>

thus, due to its dependencies, it represents the target platform for your Xtext project. If your Xtext project required some further specific dependencies to build and test, this is the place to express them!

For instance, in an Xtext project of mine, Xsemantics, I run also some SwtBot tests, which also rely on pde, thus, the dependencies in the corresponding .buckminster project’s buckminster.cspec look like

    <cs:dependencies>
        <cs:dependency name="org.eclipse.platform" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.xtext.sdk" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.swtbot.eclipse" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.swtbot.eclipse.test.junit4" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.swtbot.ide" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.pde" componentType="eclipse.feature"/>
    </cs:dependencies>

To materialize components and dependencies with Buckminster, you need a Resource Map (RMAP), and the wizard created two maps: one containing p2 repositories location (for materializing the features of your target platform), called projects-platform.rmap and one for binding your projects to the workspace (when building headlessly), called project.rmap.

projects-platform.rmap looks like

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0">
  <rm:property key="eclipse.download" value="http://download.eclipse.org"/>
  <rm:property key="xtext.p2.repository" value="${eclipse.download}/modeling/tmf/xtext/updates/composite/releases/"/>
  <rm:property key="eclipse.target.platform" value="${eclipse.download}/releases/juno"/>
  <rm:redirect pattern="org.xtext.example.hellobuck.buckminster" href="project.rmap"/>
  <rm:locator pattern="^org\.eclipse\.(?:xtext|xpand|xtend|xtend2|emf\.mwe|emf\.mwe2)(?:\..+)?$" searchPathRef="xtext"/>
  <rm:locator pattern="^com\.google.*" searchPathRef="xtext"/>
  <rm:locator pattern="^org\.antlr.*" searchPathRef="xtext"/>
  <rm:locator pattern="javax.inject" searchPathRef="xtext"/>
  <rm:locator searchPathRef="eclipse"/>
  <rm:searchPath name="xtext">
    <rm:provider componentTypes="osgi.bundle,eclipse.feature" readerType="p2" source="false">
      <rm:property key="buckminster.source" value="false"/>
      <rm:uri format="{0}">
        <bc:propertyRef key="xtext.p2.repository"/>
      </rm:uri>
    </rm:provider>
  </rm:searchPath>
  <rm:searchPath name="eclipse">
    <rm:provider componentTypes="eclipse.feature,osgi.bundle" readerType="p2" source="false" mutable="false">
      <rm:property key="buckminster.source" value="false"/>
      <rm:property key="buckminster.mutable" value="false"/>
      <rm:uri format="{0}">
        <bc:propertyRef key="eclipse.target.platform"/>
      </rm:uri>
    </rm:provider>
  </rm:searchPath>
</rm:rmap>

This basically tells Buckminster to take all Xtext stuff (including additional components like Google Guice and Antlr) from the Xtext main repository, and to use the main Eclipse Juno release repository for everything else. However, it also redirects to project.rmap for resolving the main Buckminster component of our project org.xtext.example.hellobuck.buckminster.

Again, if your target platform needs additional features from different sites, this is the place where to express them; reusing the example above which also needed SwtBot the rmap would also have these additional stuff:

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0">
  ...
  <rm:property key="swtbot.repository" value="${eclipse.download}/technology/swtbot/helios/dev-build/update-site"/>
  <rm:property key="orbit.repository" value="${eclipse.download}/tools/orbit/downloads/drops/R20120526062928/repository/"/>
  ...
  <rm:locator pattern="^org\.hamcrest*" searchPathRef="orbit"/>
  <rm:locator pattern="^org\.eclipse\.(?:swtbot)(?:\..+)?$" searchPathRef="swtbot"/>
  ...
  <rm:searchPath name="swtbot">
    <rm:provider componentTypes="osgi.bundle,eclipse.feature" readerType="p2" source="false">
      <rm:property key="buckminster.source" value="false"/>
      <rm:uri format="{0}">
        <bc:propertyRef key="swtbot.repository"/>
      </rm:uri>
    </rm:provider>
  </rm:searchPath>
  <rm:searchPath name="orbit">
    <rm:provider componentTypes="osgi.bundle,eclipse.feature" readerType="p2" source="false">
      <rm:property key="buckminster.source" value="false"/>
      <rm:uri format="{0}">
        <bc:propertyRef key="orbit.repository"/>
      </rm:uri>
    </rm:provider>
  </rm:searchPath>
  ...
</rm:rmap>

The project.rmap tells Buckminster where to find the projects of our Xtext project (so that it can bind it to the workspace when building headlessly):

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0" xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0">
  <rm:property key="projects.location" value="${workspace.root}"/>
  <rm:locator pattern="^org.xtext.example.hellobuck(?:\..+)?$" searchPathRef="project"/>
  <rm:searchPath name="project">
    <rm:provider componentTypes="eclipse.feature,osgi.bundle,buckminster" readerType="local" mutable="false">
      <rm:property key="buckminster.mutable" value="false"/>
      <rm:uri format="{0}/{1}">
        <bc:propertyRef key="projects.location"/>
        <bc:propertyRef key="buckminster.component"/>
      </rm:uri>
    </rm:provider>
  </rm:searchPath>
</rm:rmap>

This rmap assumes that all the Eclipse projects of your Xtext project are in the same base directory; if this is not the case, because you split them, for instance, in plugins, features, doc, etc. directories, then you need to tweak this rmap accordingly, for instance, again, taken from Xsemantics,

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0"
	xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0">
	<rm:property key="projects.location" value="${workspace.root}" />

	<rm:locator pattern="^it.xsemantics(?:\..+)?$"
		searchPathRef="project" />

	<rm:searchPath name="project">
		<rm:provider componentTypes="eclipse.feature,buckminster" readerType="local"
			mutable="false">
			<rm:uri format="{0}/releng/{1}">
				<bc:propertyRef key="workspace.root" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
		<rm:provider componentTypes="eclipse.feature" readerType="local"
			mutable="false">
			<rm:uri format="{0}/features/{1}">
				<bc:propertyRef key="workspace.root" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
		<rm:provider componentTypes="osgi.bundle" readerType="local"
			mutable="false">
			<rm:uri format="{0}/plugins/{1}">
				<bc:propertyRef key="workspace.root" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
		<rm:provider componentTypes="osgi.bundle" readerType="local"
			mutable="false">
			<rm:uri format="{0}/doc/{1}">
				<bc:propertyRef key="workspace.root" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
		<rm:provider componentTypes="osgi.bundle" readerType="local"
			mutable="false">
			<rm:uri format="{0}/examples/{1}">
				<bc:propertyRef key="workspace.root" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
		<rm:provider componentTypes="osgi.bundle" readerType="local"
			mutable="false">
			<rm:uri format="{0}/tests/{1}">
				<bc:propertyRef key="workspace.root" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
		<rm:provider componentTypes="eclipse.feature,osgi.bundle,buckminster"
			readerType="local" mutable="false">
			<rm:property key="buckminster.mutable" value="false" />
			<rm:uri format="{0}/{1}">
				<bc:propertyRef key="projects.location" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
	</rm:searchPath>
</rm:rmap>

Then, you have to Component Query files (CQUERY): projects-platform.cquery, to materialize the target platform, and project.cquery, to materialize your projects in the workspace. The first one could also be used in the IDE to actually materialize the target platform in your workspace (instead of using a target definition file); the second one is useful when building headless.

projects-platform.cquery:

<?xml version="1.0" encoding="UTF-8"?>
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="projects-platform.rmap">
    <cq:rootRequest name="org.xtext.example.hellobuck.buckminster" componentType="buckminster"/>
    <cq:property key="target.arch" value="*"/>
    <cq:property key="target.os" value="*"/>
    <cq:property key="target.ws" value="*"/>
    <cq:advisorNode namePattern="^.*\.source$" skipComponent="true"/>
</cq:componentQuery>

Note that this cquery has an advisor node to skip .source components: thus, the materialized target platform will not contain the sources for all the features. This is useful headlessly to reduce the time to materialize the target platform. But if you use it also for materializing the target platform in the IDE, then sources are useful to inspect Java classes, and you might want to remove this advisor node (or simply create another cquery only to be used in the IDE, without that advisor node). This query refers to projects-platform.rmap.

project.cquery:

<?xml version="1.0" encoding="UTF-8"?>
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="project.rmap">
    <cq:rootRequest name="org.xtext.example.hellobuck.site" componentType="eclipse.feature"/>
</cq:componentQuery>

As it usually happens when using Buckminster, the cquery for materializing the projects in the (headless) workspace refers to a single feature project which, transitively refers to all the bundles and additional features of your application. Usually, this is the feature project for building the p2 repository, like in this case.

“But wait! the site feature project does not refer to test projects, since I do not want to include them in my p2 repository! So, how can Buckminster run my tests headlessly if they are not materialized?”

If you look at the feature project .site, you will note that it contains a Component Extension (CSPEX) which allows to extend the automatically inferred Component Specification for the feature project with additional specifications. In this case the buckminster.cspex contains

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspecExtension xmlns:com="http://www.eclipse.org/buckminster/Common-1.0" xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0">
	<cs:dependencies>
		<cs:dependency name="org.xtext.example.hellobuck.tests" componentType="osgi.bundle" />
	</cs:dependencies>
</cs:cspecExtension>

You see that this specification adds a dependency to the org.xtext.example.hellobuck.tests project, so that, when Buckminster materializes org.xtext.example.hellobuck.site, and its dependencies, it will also materialize org.xtext.example.hellobuck.tests. You can use this technique to materialize additional projects; for instance, in from Xsemantics, I have a main feature for tests, and a tests project for each example, thus buckminster.cspex reads as follows

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspecExtension xmlns:com="http://www.eclipse.org/buckminster/Common-1.0" xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0">
	<cs:dependencies>
		<cs:dependency name="it.xsemantics.example.fj.tests" componentType="osgi.bundle" />
		<cs:dependency name="it.xsemantics.example.expressions.tests" componentType="osgi.bundle" />
		<cs:dependency name="it.xsemantics.example.lambda.tests" componentType="osgi.bundle" />
		<cs:dependency name="it.xsemantics.tests.feature" componentType="eclipse.feature" />
	</cs:dependencies>
</cs:cspecExtension>

Finally, in the .site project, you will also find the feature.xml

<?xml version="1.0" encoding="UTF-8"?>
<feature id="org.xtext.example.hellobuck.site"
	label="org.xtext.example.hellobuck.site Feature"
	version="1.0.0.qualifier">
	<includes
		id="org.xtext.example.hellobuck.sdk"
		version="0.0.0"/>
</feature>

which includes the .sdk feature of your project (Remember: when building the site.p2 on a feature project with Buckminster, you will build a p2 repository NOT for the very feature, but for the included features), and the category.xml to give categories to your features in the p2 repository:

<?xml version="1.0" encoding="UTF-8"?>
<site>
	<feature id="org.xtext.example.hellobuck.sdk" version="0.0.0">
		<category name="main"/>
	</feature>
	<feature id="org.xtext.example.hellobuck.sdk.source" version="0.0.0">
		<category name="main.source"/>
	</feature>
   <category-def name="main" label="Hellobuck"/>
   <category-def name="main.source" label="Source for Hellobuck"/>
</site>

Note that the .sdk.source feature is not a “real” feature project in your workspace, but, by default, Buckminster will automatically build a source jar for all your features and bundles.

That’s all! Many thanks to the author of this wizard, Dennis Hübner, for making it and for many suggestions!

Have fun with Bucky and Xtext :)

 

Be Sociable, Share!

Install Adobe Reader in Ubuntu 12.10 Quantal Quetzal 64bit

Acrobat Reader used to be available from Ubuntu Partner repository, but it is not available anymore in Ubuntu 12.10 Quantal Quetzal!

So you have to download the .deb package from adobe.com and install it:

http://ardownload.adobe.com/pub/adobe/reader/unix/9.x/9.5.1/enu/AdbeRdr9.5.1-1_i386linux_enu.deb

However, if you have a 64bit system, do not forget to install also these packages:

sudo apt-get install libxml2:i386 ia32-libs

Otherwise, acroread will fail

acroread: error while loading shared libraries: libxml2.so.2: cannot open shared object file: No such file or directory

Be Sociable, Share!

Materializing and Provisioning your Target Platform as local p2 site with Buckminster

This post was inspired by another blog post I had found on the web when trying to build a p2 site corresponding to a target platform defined for my projects. For an year I’ve been using Buckminster for building my Eclipse projects (especially when I had problems building my Xtext projects with Maven/Tycho, so that I decided to switch to Buckminster).

Having a p2 site for the current platform has some advantages, I guess:

  • Building RCP products will be easier (Buckminster relies on p2 directory, and all the bundles for building the product will be searched for in p2 sites);
  • It represents a (local) mirror for the target platform (for easier access).

In this post/tutorial I’ll describe my experiences

  • Define a target platform with Buckminster mechanisms (CSPEC, CQUERY and RMAP) instead of relying on target definitions with Eclipse Target Editor;
  • Build a p2 site with the contents of the so defined target platform.

In this tutorial we will create a target platform consisting of the following features

  • org.eclipse.rcp
  • org.eclipse.rcp.source
  • org.eclipse.emf.sdk
  • org.eclipse.equinox.executable

The code is available at: https://github.com/LorenzoBettini/Target_to_p2_with_Buckminster,

This tutorial will show how to materialize the target platform and build the p2 sites

  • in the IDE,
  • headlessly from the command line through ant, and
  • headlessly in Jenkins.

For the IDE you will need to install Buckminster main features in Eclipse, using the update site http://download.eclipse.org/tools/buckminster/updates-4.2.

NOTE: sometimes Buckminster’s cache in the IDE becomes stale, and you might experience errors about missing components; you might want to restart Eclipse and usually this makes the problem go away.

Why not the Target Editor?

I experienced many problems when using Eclipse Target Editor (based on p2 sites); I found it quite unreliable, especially for modifying a target definition, for updating a target definition (the Update button works 1 time out of 10); moreover, it takes some time for the target to be resolved (every time you reopen a target definition with the editor).

Furthermore, when you define a target for building RCP products, then you usually want to be able to build for several platforms, not only the current one; in these cases you have a checkbox to select (“Include all environments“):

But in that case, you must give up on “Include required software”, and this might get you into troubles about missing bundles, when building your product, if it needs to include more involved features (besides the standard “Eclipse RCP SDK” and “Eclipse Platform Launcher Executables”); for instance, if your product needs also EMF Eclipse Modeling Framework SDK (which is required when using Eclipse RCP 4.2).

Defining a target platform the “Buckminster way” does not have this limitation (and, honestly, once you get familiar with that, it’s much faster than using the target editor).

Defining a Target Platform with Buckminster

Although Buckminster is able to materialize a target platform starting from a standard target definition, it also provides an alternative way:

  1. Define a component which represents all the target features by creating a project and a custom CSPEC; this CSPEC basically declares the target features as dependencies
  2. Define a resource map (RMAP) which tells Buckminster where to find these dependencies; we will use of course official Eclipse p2 site repositories for these dependencies
  3. Define a component query (CQUERY) which materializes the component representing the target platform

In our example, this project is called bucky.example.rcpemf.target (it is a generic project without any nature). This is the project where we will define all Buckminster files (CSPEC, CQUERY and RMAP). In this project we define the component specification: buckminster.cspec

<?xml version="1.0" encoding="UTF-8"?>
<cs:cspec xmlns:cs="http://www.eclipse.org/buckminster/CSpec-1.0" name="bucky.example.rcpemf.target" componentType="buckminster" version="1.0.0">
    <cs:dependencies>
        <cs:dependency name="org.eclipse.emf.sdk" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.equinox.executable" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.rcp" componentType="eclipse.feature"/>
        <cs:dependency name="org.eclipse.rcp.source" componentType="eclipse.feature"/>
    </cs:dependencies>
</cs:cspec>

Here we use the name of the features for our target platform. (NOTE: org.eclipse.rcp and org.eclipse.rcp.source, together, correspond to Eclipse RCP SDK.)

The rmap (which we call target-platform.rmap) is defined as follows:

<?xml version="1.0" encoding="UTF-8"?>
<rm:rmap xmlns:rm="http://www.eclipse.org/buckminster/RMap-1.0"
	xmlns:bc="http://www.eclipse.org/buckminster/Common-1.0">

	<rm:property key="projects.location" value="${workspace.root}" />

	<rm:searchPath name="juno-releases">
		<rm:provider componentTypes="osgi.bundle,eclipse.feature"
			readerType="p2" source="false" mutable="false">
			<rm:uri format="http://download.eclipse.org//releases/juno" />
		</rm:provider>
	</rm:searchPath>
	<rm:searchPath name="juno-updates">
		<rm:provider componentTypes="osgi.bundle,eclipse.feature"
			readerType="p2" source="false" mutable="false">
			<rm:uri format="http://download.eclipse.org/eclipse/updates/4.2" />
		</rm:provider>
	</rm:searchPath>
	<rm:searchPath name="local-source">
		<rm:provider componentTypes="eclipse.feature,osgi.bundle,buckminster"
			readerType="local" mutable="false">
			<rm:property key="buckminster.mutable" value="false" />
			<rm:uri format="{0}/{1}">
				<bc:propertyRef key="projects.location" />
				<bc:propertyRef key="buckminster.component" />
			</rm:uri>
		</rm:provider>
	</rm:searchPath>
	<rm:locator searchPathRef="local-source" failOnError="false" />
	<rm:locator searchPathRef="juno-releases" failOnError="false" />
	<rm:locator searchPathRef="juno-updates" failOnError="true" />
</rm:rmap>

In our case we use the two main Eclipse p2 repositories (if the features you need are available from other p2 repositories, you will need to provide p2 reader types for these repositories as well). We will not use regular expressions for specifying the source p2 repositories, since there are no ambiguities in this example; instead, we simply specify the locators in the order we desire (preferring juno release site to juno updates). Note that we also have a search path for local sources. This is useful for building headlessly, so that Buckminster is able to find, resolve and bind to the workspace our own projects.

Finally, the component query (which we call target-platform.cquery) is defined as

<?xml version="1.0" encoding="UTF-8"?>
<cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="target-platform.rmap">
    <cq:rootRequest name="bucky.example.rcpemf.target" componentType="buckminster"/>
    <cq:property key="target.arch" value="*"/>
    <cq:property key="target.os" value="*"/>
    <cq:property key="target.ws" value="*"/>
</cq:componentQuery>

Thus we request the component corresponding to our project bucky.example.rcpemf.target. Note that we specify that we are not interested in any specific architecture, so that we will have a target platform for all platforms/environments/architectures. Note also that in the cquery we reference the above defined rmap.

Materializing the Target Platform

We can now materialize the target platform so defined by opening the target-platform.cquery with Buckminster corresponding editor:

WAIT: If you pressed the “Resolve and Materialize” now, Buckminster would materialize the target platform in the directory tp of a hidden project in your workspace (.buckminster). Moreover, by default, the created target platform is based on the configuration of the currently running Eclipse instance. If you want to start from a plain and empty platform (just like you do with a standard target definition with the target editor), there are a few more steps to perform:

  1. Create an empty target platform manually that contains one single and empty directory.
  2. Set this target platform active.
  3. A subsequent resolution/materialization will use that platform.

You can specify any directory of your filesystem, in any case, make sure the directory you choose already exists.

One possible way of doing this, as illustrated also here, is

  1. Create a new general project named TP (or some name of your preference) in the workspace
  2. In “Window” => “Preferences” => “Plug-in Development” => “Target Platform”
    Select Add…
  3. Start with an empty target definition
  4. Enter TP in the Name: field (or some name of your preference)
  5. Add a directory
  6. Click on “Variables…” scroll down and select “workspace_loc” and then type TP in the Argument: field

This procedure is shown by the following screenshots.

NOTE: these additional steps are not required when building headlessly

Once you pressed Finish and set this new target as the active target platform, you’re ready to materialize the cquery from the cquery editor. Of course, it might take some time for downloading all the features. Once the materialization is finished, if you followed the above procedure and created a general project TP in your workspace, you can see the materialized target platform

Create a feature for the p2 site for your target platform

Once the target platform is resolved (you can also have a look at the current new target platform from the Eclipse preferences), we are ready to create a feature that we use to create the p2 site corresponding to our target platform.

We thus create a new feature project, that we call bucky.example.rcpemf.target.site, and we initialize it with all the bundles (plugins and fragments) of the current target platform (if you have other bundle projects in your workspace, make sure to unselect such additional workspace projects)

Before creating the p2 site, you may want to create a buckminster.properties (e.g., in the main project bucky.example.rcpemf.target) where we set some properties for Buckminster (e.g., that we want to build a site for all environments, and that we want the site to be created in a specific folder, in this example /tmp/bucky):

# Where all the output should go
buckminster.output.root=/tmp/bucky/build
# Where the temp files should go
buckminster.temp.root=/tmp/bucky
# How .qualifier in versions should be replaced
qualifier.replacement.*=generator:lastRevision

target.os=*
target.ws=*
target.arch=*

We are now ready to build a p2 site for this feature with Buckminster:

  1. right click on the bucky.example.rcpemf.target.site project
  2. select Buckminster -> Invoke Action…
  3. select the action site.p2 (and, additionally, select the buckminster.properties file above)


If you used the same property file, you can find the site.p2 in /tmp/bucky/build/bucky.example.rcpemf.target.site_1.0.0-eclipse.feature/site.p2/ .

The p2 site you’ve just created could already be used, for instance, for building your RCP product with Buckminster through the p2 director. However, as it is, it contains only bundles, no (installable) features, thus it cannot be used, for instance, as a mirror for your target platform… see the next section

Create a feature for the p2 MIRROR site for your target platform

We create a new feature project bucky.example.rcpemf.target.mirror.site, and, as before, we initialize it with all the bundles (plugins and fragments) of the current target platform (if you have other bundle projects in your workspace, make sure to unselect such additional workspace projects); but this time, once the feature project is created, we also add to the feature.xml all the features that we used to create our target platform:

Let’s run the action site.p2 (using the same buckminster.properties file) on this new feature project. This time, we will end up with a p2 site with all the installable features of our target platform! You can verify this by using the Eclipse install new features menu and using as repository the one just created (if you used the same output directory it will be located at /tmp/bucky/build/bucky.example.rcpemf.target.mirror.site_1.0.0-eclipse.feature/site.p2/).

Even more, you might create a target definition file, open it with the Eclipse target editor, and create a target definition using your local mirror!

Headless execution from the command line

If you want to materialize the target platform and build the p2 site from the command line, you need to install the headless version of Buckminster.

For instance, you download the director from http://www.eclipse.org/buckminster/downloads.html and then you run the director as follows

director -r \
   http://download.eclipse.org/tools/buckminster/headless-4.2/ \
   -d <WHERE_TO_INSTALL> -p Buckminster \
   -i org.eclipse.buckminster.cmdline.product \
   -i org.eclipse.buckminster.core.headless.feature.feature.group \
   -i org.eclipse.buckminster.pde.headless.feature.feature.group

Headlessly, we will need to

  1. resolve the cquery for the target platform (that we already showed above);
  2. resolve the cquery for the site feature, (in this case, it is the one for the mirror site), mirror-project.cquery:
    <?xml version="1.0" encoding="UTF-8"?>
    <cq:componentQuery xmlns:cq="http://www.eclipse.org/buckminster/CQuery-1.0" resourceMap="target-platform.rmap">
        <cq:rootRequest name="bucky.example.rcpemf.target.mirror.site" componentType="eclipse.feature"/>
        <cq:property key="target.arch" value="*"/>
        <cq:property key="target.os" value="*"/>
        <cq:property key="target.ws" value="*"/>
    </cq:componentQuery>

    Note we reuse the same rmap we saw before. This way, during the materialization of the mirror site feature, possible additional dependencies will be resolved by Buckminster and added to the target platform;

  3. perform the site.p2 action (before we also perform a buckminster.clean) on the component of the mirror site

We then write an ANT file, build.ant, in the project bucky.example.rcpemf.target, as follows (this was inspired by the one generated by the Xtext wizard, developed by Dennis HübnerI’ve blogged about that, and from the one that can be found here):

<?xml version="1.0" encoding="UTF-8"?>
<!--
     Buckminster Headless - build

     buckminster.home must be specified on the command line, e.g.,
         ant -Dbuckminster.home=/home/bettini/buckminster -f build.ant

     Properties:
         WORKSPACE              Eclipse workspace location, or hudson job workspace
         build.root             Where to build? WARNING: This folder will be cleaned up, so do not point to user.home or something important
                            Default: ${WORKSPACE}/buildroot
        buckminster.home    Buckminster headless to use. See http://www.eclipse.org/buckminster/downloads.html
        projects.location    Where to find projects to build?
                            Default: ${WORKSPACE}
-->
<project name="Buckminster Headless" default="buckminster">
    <property name="WORKSPACE" location="${ant.file}/../../" />
    <property name="build.root" location="${WORKSPACE}/buildroot" />
    <property name="projects.location" location="${WORKSPACE}" />
    <property name="resolve.commands.file" location="${projects.location}/bucky.example.rcpemf.target/headless-resolve-commands.txt" />
    <property name="perform.commands.file" location="${projects.location}/bucky.example.rcpemf.target/headless-perform-commands.txt" />
    <property name="target.platform" value="target.platform" />

    <target name="buckminster" depends="cleanup" description="description">
        <fail unless="buckminster.home" message="buckminster.home must be specified." />

        <echo message="IMPORTANT: Populating an empty target platform may took over 10 minutes." />

        <java fork="true" dir="${buckminster.home}" logError="true" classname="org.eclipse.core.launcher.Main" failonerror="true">
            <classpath>
                <fileset dir="${buckminster.home}/plugins">
                    <include name="org.eclipse.equinox.launcher_*.jar" />
                </fileset>
            </classpath>
            <arg line='-update' />
            <arg line='-data "${build.root}/buckminster.workspace"' />
            <arg line='-configuration "${build.root}/configuration"' />
            <arg line='--script "${resolve.commands.file}"' />
            <sysproperty key="projects.location" value="${projects.location}" />
            <sysproperty key="buckminster.output.root" value="${build.root}/buckminster.output" />
            <sysproperty key="buckminster.temp.root" value="${build.root}/buckminster.temp" />
            <sysproperty key="target.platform" value="${build.root}/${target.platform}" />
            <jvmarg line=" -Xms256m -Xmx512m" />
        </java>

        <java fork="true" dir="${buckminster.home}" logError="true" classname="org.eclipse.core.launcher.Main" failonerror="true">
            <classpath>
                <fileset dir="${buckminster.home}/plugins">
                    <include name="org.eclipse.equinox.launcher_*.jar" />
                </fileset>
            </classpath>
            <arg line='-update' />
            <arg line='-data "${build.root}/buckminster.workspace"' />
            <arg line='-configuration "${build.root}/configuration"' />
            <arg line='--script "${perform.commands.file}"' />
            <sysproperty key="projects.location" value="${projects.location}" />
            <sysproperty key="buckminster.output.root" value="${build.root}/buckminster.output" />
            <sysproperty key="buckminster.temp.root" value="${build.root}/buckminster.temp" />
            <sysproperty key="target.platform" value="${build.root}/${target.platform}" />
            <jvmarg line=" -Xms256m -Xmx512m" />
        </java>

        <echo message=" " />
        <echo message="Updatesite output in: ${build.root}/buckminster.output/bucky.example.rcpemf.target.mirror.site_*-eclipse.feature/site.p2/" />
    </target>

    <target name="cleanup">
        <delete failonerror="false" includeemptydirs="true">
            <fileset dir="${build.root}" defaultexcludes="false">
                <exclude name="**/.metadata/.plugins/org.eclipse.pde.core/.bundle_pool/" />
                <exclude name="**/${target.platform}/" />
            </fileset>
        </delete>
    </target>

    <target name="reset.target-platform">
        <delete includeemptydirs="true">
            <fileset dir="${build.root}" defaultexcludes="false">
                <include name="**/.metadata/.plugins/org.eclipse.pde.core/.bundle_pool/" />
                <include name="**/${target.platform}/" />
            </fileset>
        </delete>
    </target>
</project>

You will need to run ant passing this file and also specifying the path where your headless Buckminster is installed, in my case I run

ant -Dbuckminster.home=/home/bettini/buckminster -f build.ant

This ant script runs Buckminster twice:

  1. The first time it runs the materialization commands (stored in the file bucky.example.rcpemf.target/headless-resolve-commands.txt)
    setpref targetPlatformPath="${target.platform}"
    resolve "${projects.location}/bucky.example.rcpemf.target/target-platform.cquery"
    resolve "${projects.location}/bucky.example.rcpemf.target/mirror-project.cquery"
  2. Then it runs the actual commands to build the p2 site (stored in the file bucky.example.rcpemf.target/headless-perform-commands.txt); in this case we only build the p2 site for the mirror feature
    clean
    build
    perform -D target.os=* -D target.ws=* -D target.arch=* "bucky.example.rcpemf.target.mirror.site#buckminster.clean"
    perform -D target.os=* -D target.ws=* -D target.arch=* "bucky.example.rcpemf.target.mirror.site#site.p2"

You need to execute Buckminster twice because of some conflicting bundles (see the discussion here) which cause problems if you attempt to run everything in one shot; if you did not separate the steps, you would get something like

INFO:  perform '-D' 'target.os=*' '-D' 'target.ws=*' '-D' 'target.arch=*' 'bucky.example.rcpemf.target.site#site.p2'
CSpec org.apache.lucene.core:osgi.bundle$3.5.0.v20120319-2345 has no  action, group, or local artifact named bundle.and.fragments

Once the script is finished you will get the p2 site in the subdirectory buildroot/buckminster.output/bucky.example.rcpemf.target.mirror.site_*-eclipse.feature/site.p2.

Headless execution in Jenkins

The last task is to build headlessly in Jenkins; of course, this assumes you have a working Jenkins installation with the Buckminster plugin (I’ve blogged about that also).

We write the commands to execute in two text files (similar to the ones shown in the previous section):

  • bucky.example.rcpemf.target/jenkins-resolve-mirror-commands.txt
    resolve 'bucky.example.rcpemf.target/target-platform.cquery'
    resolve 'bucky.example.rcpemf.target/project.cquery'
  • bucky.example.rcpemf.target.mirror.site/jenkins-perform-commands.txt
    clean
    build
    perform -D target.os=* -D target.ws=* -D target.arch=* bucky.example.rcpemf.target.mirror.site#buckminster.clean
    perform -D target.os=* -D target.ws=* -D target.arch=* bucky.example.rcpemf.target.mirror.site#site.p2

Then we can create a Jenkins job, which fetches the sources from the git repository

specify two Buckminster execution steps (as noted in the previous section, this is mandatory for the whole process to succeed):

and archive the artifacts

When the job finishes, you can see the archived p2 site

That’s all…

I hope you enjoyed this post, and comments are more than welcome :)

Be Sociable, Share!

Accessing your remote Ubuntu machine with VNC and ssh

If you want to access your remote Ubuntu machine with VNC, in particular by tunnelling through ssh, there is already some documentation which can be found here. However, at least for me, the procedure explained there does not work out of the box. So here’s what I had to do to make it work.

First of all you need to install in the machines the following packages:

  • remote machine: xvfb x11vnc openssh-server
  • local machine: xtightvncviewer openssh-client

Then, the script to run on your client machine to access the server has to be slightly modified as follows

#!/bin/sh

ssh -C -f -L 5900:localhost:5900 USER@REMOTEIP \
        x11vnc -safer -localhost -nopw -once \
        -auth /home/USER/.Xauthority -display :0 -create \
        && sleep 5 \
        && vncviewer localhost:0

where you will have to replace USER with your user on the remote machine, and REMOTEIP with the address of your remote machine.

Basically, the changes I had to make to the original script were to add the -auth command line option specifying the path to the .Xauthority, and the command line option -create to actually start an instance of the X server on the remote machine.

Be Sociable, Share!