Getting Xcore to work in Bndtools
This example project shows how Xcore can work within Bndtools. It’s divided into two sub-goals:
- Get Xcore to work via the Eclipse UI with Bndtools
- Get Xcore to work via Bnd Gradle Plugin on the command line
Getting Xcore to Work via Eclipse UI
High level:
- Create and configure an Xcore project
- Add Xcore-related repositories and dependencies using Bndtools semantics
- Customize for Equinox runtime
- Compile and test the Xcore model
Create and Configure Xcore Project
(Note: the example uses the project name and package name of com.example.bndtools.xcore.model
.)
- Create a Bnd workspace based on the GitHub “bndtools/workspace” template
- Create a new project: “Bnd OSGi Project” → “OSGi Standard Templates” → “Component Development”. Consider this the “Xcore project”
- Via context menu on above project, select “Configure” → “Convert to Xtext Project”
- Via context menu root project (which contains “cnf”), select “Configure” → “Convert to Gradle Project”
- Create the following basic Xcore model in the Xcore project, saved in the “model/Model.xcore” file. (Note: the “model” directory is not a source directory.)
@GenModel(
bundleManifest="false",
updateClasspath="false",
modelDirectory="/com.example.bndtools.xcore.model/src",
oSGiCompatible="true",
forceOverwrite="true"
)
package com.example.bndtools.xcore.model
class One
{
refers Two two opposite one
}
class Two
{
refers One one opposite two
}
Add repositories and dependencies using bndtools semantics
- Resolve the Xcore dependencies (i.e.
@GenModel
annotation) by adding the following repositories tobuild.bnd
cnf project:
-plugin.5.Xtext: \
aQute.bnd.repository.p2.provider.P2Repository; \
url = http://download.eclipse.org/modeling/tmf/xtext/updates/releases/2.10.0/; \
name = Xtext
-plugin.6.EmfCore: \
aQute.bnd.repository.p2.provider.P2Repository; \
url = http://download.eclipse.org/modeling/emf/emf/updates/2.10.x/core/S201501230452/; \
name = EmfCore
-plugin.7.EmfBase: \
aQute.bnd.repository.p2.provider.P2Repository; \
url = http://download.eclipse.org/modeling/emf/emf/updates/2.10.x/base/S201501230348/; \
name = EmfBase
-plugin.8.EmfXcore: \
aQute.bnd.repository.p2.provider.P2Repository; \
url = http://download.eclipse.org/modeling/emf/emf/updates/2.10.x/xcore/R201502020452/; \
name = EmfXcore
# Downloads everything, will be slow
# Currently only needed for the one JDT dependency
-plugin.9.Neon: \
aQute.bnd.repository.p2.provider.P2Repository; \
url = http://download.eclipse.org/eclipse/updates/4.6/R-4.6.1-201609071200/; \
name = Neon
- Add the following build dependencies to the Xcore project’s
bnd.bnd
:org.eclipse.emf.ecore
org.eclipse.xtext.xbase.lib
org.eclipse.emf.ecore.xcore.lib
org.eclipse.emf.common
org.eclipse.xtext.ecore
org.eclipse.emf.codegen.ecore.xtext
org.eclipse.emf.ecore.xcore
org.eclipse.xtext
org.eclipse.xtext.xbase
org.eclipse.emf.codegen.ecore
org.eclipse.jdt.core
Customize For Equinox Runtime
- Modify the Xcore
bnd.bnd
to include the following:
# plugin.xml and its properties are needed
# To generate these, edit and save Xcore model
# Model not needed for runtime
Include-Resource: plugin.xml, plugin.properties, OSGI-OPT/model=model
# The bsn needs to specify the singleton attribute
Bundle-SymbolicName: ${p};singleton:=true
- Export all of the auto-generated packages:
# Mirrors what the auto-generated plugin.xml declares
Export-Package: \
com.example.bndtools.xcore.model,\
com.example.bndtools.xcore.model.impl,\
com.example.bndtools.xcore.model.util
Compile and test the Xcore model
After saving bnd.bnd
, which triggers a build, Xcore should auto-generate
the following source and related files:
src/com.example.bndtools.xcore.model.*
Java filesbuild.properties
plugin.properties
plugin.xml
Note: Xcore shouldn’t add any additional libraries to the Xcore project build path.
Unit Test
Refer to the Testing the Provider with %28Standard%29 JUnit section for background on unit testing in Bndtools.
- In the Xcore project, add the following to
test/com.example.bndtools.xcore.model/ExampleTest.java
:
@Test
public void testXcore() {
One one = ModelFactory.eINSTANCE.createOne();
Two two = ModelFactory.eINSTANCE.createTwo();
one.setTwo(two);
assertEquals(one, two.getOne());
}
Running the above as a standard JUnit test should successfully execute.
Integration Test
Refer to the Testing in OSGi section for background on integration testing in bndtools.
By default, Xcore uses the package name of the model as the EMF namespace
URI (nsURI). Xcore registers this nsURI using the Equinox Extension Registry,
declared in the Xcore project’s plugin.xml
file. The nsURI is registered in
the EMF Package Registry.
The integration test below queries the EMF Package Registry for the model’s nsURI. If found, it implies the bundle was able to register its extension point to the Equinox Extension Registry and register the model’s nsURI to the EMF Package Registry.
- Create a new project: “Bnd OSGi Project” → “OSGi Standard Templates” → “Integration Testing”. Consider this the ITest project.
- Add the following to the Build Path in the ITest
bnd.bnd
:org.eclipse.emf.ecore
org.eclipse.emf.common
com.example.bndtools.xcore.model
- Modify the following in the
bnd.bnd
Run configuration:- In the “Core Runtime” section:
- “OSGi Framework”:
org.eclipse.osgi
. Do not choose Felix since Equinox-specific extensions are used. - Execution Env:
JavaSE-1.8
or similar
- “OSGi Framework”:
- In the “Run Requirements”:
- The model and test bundles
org.eclipse.emf.ecore
org.eclipse.emf.common
org.eclipse.xtext.xbase.lib
org.eclipse.emf.ecore.xcore.lib
org.eclipse.core.resources
- Click on the “Resolve” button and save
- In the “Core Runtime” section:
- Add the following test to
/com.example.bndtools.xcore.test/src/com/example/bndtools/xcore/test/ExampleIntegrationTest.java
:
@Test
public void shouldBeRegistered() {
String nsURI = "com.example.bndtools.xcore.model";
EPackage.Registry registry = EPackage.Registry.INSTANCE;
EPackage ePackage = registry.getEPackage(nsURI);
assertNotNull(ePackage);
}
- Via the context menu on the ITest project, select “Run As” → “Bnd OSGi Test Launcher (JUnit)”.
This should successfully execute.
Get Xcore to work via Gradle on the command line
- Create “build.gradle”
- Build jar
- Add plugin as dependency
Create “build.gradle”
Per the Bnd Gradle Plugin README:
If special Gradle build behavior is needed, beyond changes to the project’s
bnd.bnd
file, then you should place abuild.gradle
file in the root of the project and place your customizations in there.
- Create a new
build.gradle
file in the Xcore project with the following:
plugins {
id 'org.xtext.builder' version '1.0.12'
}
// Needed for plugin repository
repositories {
jcenter()
}
ext.xtextVersion = "2.10.0"
// Non-plugin dependencies managed via bnd.bnd
dependencies {
compile "org.eclipse.xtext:org.eclipse.xtext:${xtextVersion}"
compile "org.eclipse.xtext:org.eclipse.xtext.xbase:${xtextVersion}"
compile 'org.eclipse.emf:org.eclipse.emf.ecore.xcore.lib:+'
xtextLanguages 'org.eclipse.emf:org.eclipse.emf.ecore.xcore:+'
xtextLanguages 'org.eclipse.emf:org.eclipse.emf.ecore.xcore.lib:+'
xtextLanguages 'org.eclipse.emf:org.eclipse.emf.codegen.ecore:+'
xtextLanguages 'org.eclipse.emf:org.eclipse.emf.codegen.ecore.xtext:+'
xtextLanguages "org.eclipse.xtext:org.eclipse.xtext.ecore:${xtextVersion}"
xtextLanguages 'org.eclipse.jdt:org.eclipse.jdt.core:+'
}
xtext {
version = "${xtextVersion}"
languages {
ecore {
setup = 'org.eclipse.xtext.ecore.EcoreSupport'
}
codegen {
setup = 'org.eclipse.emf.codegen.ecore.xtext.GenModelSupport'
}
xcore {
setup = 'org.eclipse.emf.ecore.xcore.XcoreStandaloneSetup'
generator.outlet.producesJava = true
}
}
sourceSets {
main {
srcDir 'model'
// Move the generated Xcore output to the src directory
output {
dir(xtext.languages.xcore.generator.outlet, 'src')
}
}
}
}
Notes on the above:
- The added repository section is needed for plugin dependency resolution
- The
compile
andxtextLanguages
dependencies are managed via the Xcore project’sbnd.bnd
file - The
srcDir 'model'
directive tells Xtext to use themodel
directory as its source directory - The generated source output is moved to Bndtools’s default source directory
Build jar
The below uses Buildship to visually control Gradle.
- Install Buildship
- Open “Gradle Executions” and “Gradle Tasks” views
- In “Gradle Tasks”, select the Xcore project, “build” folder, “jar” task, execute it:
:com.example.bndtools.xcore.model:generateXtext
:com.example.bndtools.xcore.model:compileJava
:com.example.bndtools.xcore.model:processResources UP-TO-DATE
:com.example.bndtools.xcore.model:classes
:com.example.bndtools.xcore.model:jar
BUILD SUCCESSFUL
Total time: 14.425 secs
You should see something similar to the above.
Prev