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.
@GenModelannotation) by adding the following repositories tobuild.bndcnf 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.ecoreorg.eclipse.xtext.xbase.liborg.eclipse.emf.ecore.xcore.liborg.eclipse.emf.commonorg.eclipse.xtext.ecoreorg.eclipse.emf.codegen.ecore.xtextorg.eclipse.emf.ecore.xcoreorg.eclipse.xtextorg.eclipse.xtext.xbaseorg.eclipse.emf.codegen.ecoreorg.eclipse.jdt.core
Customize For Equinox Runtime
- Modify the Xcore
bnd.bndto 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.propertiesplugin.propertiesplugin.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.ecoreorg.eclipse.emf.commoncom.example.bndtools.xcore.model
- Modify the following in the
bnd.bndRun 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.8or similar
- “OSGi Framework”:
- In the “Run Requirements”:
- The model and test bundles
org.eclipse.emf.ecoreorg.eclipse.emf.commonorg.eclipse.xtext.xbase.liborg.eclipse.emf.ecore.xcore.liborg.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.bndfile, then you should place abuild.gradlefile in the root of the project and place your customizations in there.
- Create a new
build.gradlefile 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
compileandxtextLanguagesdependencies are managed via the Xcore project’sbnd.bndfile - The
srcDir 'model'directive tells Xtext to use themodeldirectory 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