Load selected plugins before headless build



TLDR: How do I enforce that a specific self-made plugin is loaded during a headless build?


I try to execute a headless build for a module and before the build starts, I want MPS to load a self-made MPS plugin that is not directly a dependency of the module. It seems like that during a headless build, this plugin is not loaded because my module does not directly depend on it.

My goal is to inject different runtimes for different build environments with the help of extensions and extension points.

  • In the RCP and dev environment I deploy a plugin that implements the extension points for the production environment
  • In headless environments (test execution and simple module build) I try to deploy a headless runtime plugin, that implements the extension points for headless environments

This strategy works fine for RCPs, development and even for the headless test run.

In the headless test run you can "load additional idea plugins" and this works fine. 


I'm searching something similar for simple headless builds. Does anyone have an idea?

Comment actions Permalink

Tests run in so called "IDEA environment", generation runs in "MPS environment". The MPS environment is lighter but less featured. Application and project plugins seem to not be loaded in MPS environment, however extensions from eligible modules are loaded and activated.

Eligible modules are either solutions whose solution kind is set to a value other than None, or languages.

Comment actions Permalink

Interesting. I checked my current build setup and I saw that my modules already have the solution kind = Other

I have 3 solutions for this purpose:

  1. app.runtime (kind: Other, contains the extension points)
  2. app.runtime.main (kind: Other, contains the extension implementation for RCP/dev environments)
  3. app.runtime.headless (kind: Other, contains the extension implementation for headless environments)

My build pipeline of my production model is as follows:

  1. Build all of my main languages and solutions in the initial build script, let's call it "main.build" (also contains app.runtime to provide the extension point)
  2. Build "app.runtime.headless" in a separate build script, that packages this solution into a dedicated plugin, let's call this build script "headless.runtime.build". This script depends on "main.build", because "main.build" provides the necessary app.runtime dependency.
  3. Finally, the generation build, which just builds 1 module, depends on "main.build" (because the languages and solutions are necessary dependencies for the module) and "headless.runtime.build". 

I first execute the ant task for script 1, then script 2 and then script 3. The generation build succeeds but doesn't load the headless runtime plugin. Maybe I should mention that build script 3 is executed in a standalone environment, where all generated plugins are deployed inside the "plugins" directory. Shouldn't make a difference though :/


Comment actions Permalink

To be clear, when I was talking about extensions, I meant concepts from jetbrains.mps.lang.extension language (extension point and extension). Only they get loaded and activated when in MPS environment.

Comment actions Permalink

I also mean these concepts.

I have an extension point (ExtensionPointDeclaration concept) in app.runtime, which is used throughout the project and accessed via


I inject different extension point implementations (Extension concept) via two solutions, one is deployed to RCP environments and the other one to headless MPS environments.


If I understand you correctly there can be two types of headless environments during build script execution:

  1. test runs => IDEA Environment (loads plugin and activates/deactivates the extension correctly thanks to thesection)
  2. generation runs => MPS Environments (does not load the plugin and does not activate/deactivate the extension)




Comment actions Permalink

In my experience MPS environment does activate the extension. But it needs to be put in the proper place (in `app.runtime.plugin` model of app.runtime and app.runtime.headless.plugin of app.runtime.headless).

Also, at least one of the modules in your script 3 should, I believe, have a dependency on app.runtime.headless in order for it to be put on the classpath and loaded.

Comment actions Permalink




Give me second to check if it helps to manually add the dependency to a module

Comment actions Permalink

After I manually added app.runtime.headless as dependency to at least one module of my build script, everything worked like a charm (I did it for every module, cause why not).

Thank you very much, this little detail took me longer than it should have.


Maybe it is a good idea in the future to be able to define such dependencies as general dependencies inside a BuildProject node? (like for test run configurations?).

It is difficult to figure out why this dependency is explicitly needed there. For example, if new modules are added to this build script, every team member has to remember to add the headless runtime dependency to this module, because as soon as the last module with this dependency is removed from the build script, it suddenly stops working.

Comment actions Permalink

The generator does not load the entire project but rather computes the minimal set of modules it needs to load, probably for performance reasons. If there is no dependency on a given module, it does not end up in the set.

I think your suggestion to add configuration for explicit dependencies to the build script is a good one and I encourage you to file it on youtrack.jetbrains.com. But keep in mind that the pace of development of MPS is rather slow and this is highly unlikely to be implemented soon.


Please sign in to leave a comment.