<< Docker: Use host-network on docker container | Home | xtext - create update site with your plugin >>

xtext - export dsl as runnable jar

If you write an xtext-dsl you get a great editor and generator inside of eclipse. But there are times you want the generator to generate the code outside of eclipse. e.g. for using in a automated workflow.

I'm not sure what new options were introduced since XText 2.8 but I guess it is worth mentioning nonetheless.

Here are the steps to take:

  1. Make sure to add generateJavaMain = true to your DSL's mwe2-file:

    fragment = generator.GeneratorFragment auto-inject {
      generateJavaMain = true
    }

    Next time you rerun mwe2 (right-click on your mwe2-file => run-as mwe2) a file called Main.java will be generated in the Generator-Folder

  2. Create a Run-Configuration to start the generated Main.java

  3. Export your dsl as runable-jar:
  • right-click on your dsl-project => export=>Java=>Runnable Jar File
  • Select the Launch-Configuration that is starting the Main.java
  • Select the output-Folder
  • Using the Save as Ant-Script is optional but becomes handy if you are testing a lot.
    Once you have create this you can call it to pack the jar again. (It will not build, this is usually done automatically by eclipse) e.g. like this

      ant -f packjar.xml
  1. Your basically done. You can now create your generated output by calling:

      java --jar mydsl-runnable.jar input.mydsl

This will usually create the output in a src-gen-folder. If you want to override this behaviour you can use OutputConfigurations.

Optional:

  • To change the outputFolder you can change the outputPath in the Main.java:

      // configure and start the generator
      fileAccess.setOutputPath("src-gen/");
  • More advanced are output-configurations. In this you can e.g. tell the dsl's filesystem how to behave if a file is already generated. In one project I wanted some files to overwrite old versions and some files to be created once and never overwrite those (e.g. because I want the user to add their logic in there). Here is an example. You have to replace the setOutputPath-Part with those lines in Main.java:

  String outputFolder = "./out";

  OutputConfiguration defaultOutput = new OutputConfiguration(IFileSystemAccess.DEFAULT_OUTPUT);
  defaultOutput.setDescription("Output Folder");
  defaultOutput.setOutputDirectory(outputFolder+"/src-gen");
  // tell the fsa to override(!) existing resources!!
  defaultOutput.setOverrideExistingResources(true);
  defaultOutput.setCreateOutputDirectory(true);
  defaultOutput.setCleanUpDerivedResources(true);
  defaultOutput.setSetDerivedProperty(true);

  OutputConfiguration genonceOutput = new OutputConfiguration("gen-once");
  genonceOutput.setDescription("Generate Once Output Folder");
  genonceOutput.setOutputDirectory(outputFolder+"/src-nodes");
  // tell the fsa to NOT override existing resources!!
  genonceOutput.setOverrideExistingResources(false);
  genonceOutput.setCreateOutputDirectory(true);
  genonceOutput.setCleanUpDerivedResources(false);
  genonceOutput.setSetDerivedProperty(false);

  Map<String,OutputConfiguration> fsaConfs = new HashMap<>();
  fsaConfs.put(IFileSystemAccess.DEFAULT_OUTPUT, defaultOutput);
  fsaConfs.put("gen-once",genonceOutput);

  fileAccess.setOutputConfigurations(fsaConfs);

You can access the different Configurations like this:

  fsa.generateFile(String fileName,String outputConfigurationName,CharSequence contents);

Obviously this all makes only sense if you also created something like this in your eclipse-runtime.

Sry, for the redundant code here. You actually should have one solution that get's called at an appropriate time. Ok, here we go:

  • Create an xtend-class 'CustomOutputConfigurationProvider.xtend' in your dsl's main-folder with this content (make sure to adapt package and other things that might differ):
  package org.tt.gen

  import java.util.Set
  import org.eclipse.xtext.generator.OutputConfiguration
  import org.eclipse.xtext.generator.IOutputConfigurationProvider
  import org.eclipse.xtext.generator.IFileSystemAccess

  public class CustomOutputConfigurationProvider implements IOutputConfigurationProvider {

    public static final String GEN_ONCE_OUTPUT = "gen-once";

    /**
     * @return a set of {@link OutputConfiguration} available for the generator
     */
     override def Set<OutputConfiguration> getOutputConfigurations() {
      val OutputConfiguration defaultOutput = new OutputConfiguration(IFileSystemAccess.DEFAULT_OUTPUT);
      defaultOutput.setDescription("Output Folder");
      defaultOutput.setOutputDirectory("./src-gen");
      defaultOutput.setOverrideExistingResources(true);
      defaultOutput.setCreateOutputDirectory(true);
      defaultOutput.setCleanUpDerivedResources(true);
      defaultOutput.setSetDerivedProperty(true);

      val OutputConfiguration readonlyOutput = new OutputConfiguration(GEN_ONCE_OUTPUT);
      readonlyOutput.setDescription("Read-only Output Folder");
      readonlyOutput.setOutputDirectory("./src-nodes");
      readonlyOutput.setOverrideExistingResources(false);
      readonlyOutput.setCreateOutputDirectory(true);
      readonlyOutput.setCleanUpDerivedResources(false);
      readonlyOutput.setSetDerivedProperty(false);
      return newHashSet(defaultOutput, readonlyOutput);
    }
  }
  • Now we need to tell the runtime-version to use our new custom outputconfiguration-provider. (Viva dependency injection!!).
    Add following lines in your DSL's runtime-module-class' configure-method that is located in your DSL's main-folder:

      binder.bind(IOutputConfigurationProvider.class)
    .to(CustomOutputConfigurationProvider.class)
    .in(Singleton.class);

That should be it.

Tags : ,

Export this post as PDF document  Export this post to PDF document

Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!
Home