Skip to content
DomenikP edited this page Jul 28, 2016 · 47 revisions

This page describes how to setup a build for MPS projects that are based on the mbeddr platform or on mbeddr itself. If your project depends on mbeddr, please continue reading in mbeddr, otherwise, please continue reading in mbeddr Platform.

Resolving the mbeddr and the mbeddr platform Release

You can either download the mbeddr and the mbeddr platform release from our GitHub release page, or resolve these artifacts from our Nexus by using a Gradle script that can be found inside the mbeddr.core repository:

mbeddr.core
└─download.gradle

This script provides two tasks, one for resolving the required MPS distribution (resolveMPS), one for resolving the mbeddr release (resolveMbeddr) and another one for resolving the mbeddr platform release (resolvePlatform). On top, the script declares two variables that specify where resolved artifacts should be copied, these paths can be overwritten from outside when executing the script. Per default, the resolved MPS is put inside a folder <current directory>/mps (mpsLocation), whereas the mbeddr platform is put to <current directory>artifacts (artifacstLocation).

mbeddr Platform

This section describes a template that we have created for illustrating how to setup depending on the mbeddr platform. Further, we discuss for an example Base Language extension using the platform how to setup a build script by using this template.

Build Script Template

We have created a template illustrating how to setup a MPS build script for building a MPS project on top of the mbeddr platform. This template is named platform-extension.template and is shipped with the mbeddr platform distribution that can be found on the release page. If you use the mbeddr platform from sources, you can find the template inside the the mbeddr build project that can be found here:

mbeddr.core
└─code
  └─languages
    └─com.mbeddr.build

This template declares on top (see screenshot below) a set of macros that we use for resolving paths during the build, e.g., mps.home refers to your MPS installation, artifacts.root points to a file system location where all of your dependencies, such as the mbeddr platform, will be located, finally, platform.distribution.artifacts refers to the location of the mbeddr platform distribution, a build artifact representing the compiled and packaged mbeddr platform release. We will later demonstrate how to overwrite the specified paths for mps.home and artifacts.root to fit your environment, please ignore the values of these macros for now.

Macros defined in build script template

Below the macros section is the dependencies section (see screenshot below) that defines through referenced build scripts a set of artifacts that have to be present at build time. In our template we define dependencies on mps, mpsBuild and mpsDebuggerPlugin, all three coming with MPS. Further, we use the previously described mps.home macro to resolve these artifacts from the MPS installation. You can specify artifact locations by typing an opening parenthesis behind the build script name. It's good practice to have such an artifact locations for each dependency. Besides MPS, we also define a dependency on the build script com.mbeddr.platform.distribution, which is responsible for packaging all plugins being shipped with the mbeddr platform. This way, the build will resolve the mbeddr platform plugins as build dependencies.

Build time Dependencies defined in build script template

Below the dependencies section is the project structure that is used for configuring the build, describing plugin descriptors and listing all solutions and languages that should be built. On top of this section (see screenshot below), we have generator options being used for configuring the code generator with the same options that we use in mbeddr. Next, java options configures the Java compiler being used for compiling languages, and solutions containing Base Language code. Next, is a template for an idea plugin (see screenshot below) that contains dummy names, which you should replace with project-specific names. Each idea plugin ends up in an idea plugin descriptor, serialized to xml and packaged with the compiled plugin code. While these plugin descriptors specify a set of names, they additionally require a version number, optional vendor information, content referring to solutions and language described in same section and being packaged with the plugin. Finally, runtime dependencies lists other plugins that should be available in the MPS target environment where your plugin is deployed.

Below the idea plugin is a mps group <your solutions/languages group> that you can use for grouping languages and solutions that you want to build and package in a plugin. After copying the template, please change the group name accordingly to your project. Inside this group, you can either type the word language or solution on the cell containing the text <empty> to specify a module that you want to build with your build script. Next, you can specify in the load from section of your instantiated module a path to the .msd (solution) or .mpl (language) file that contains meta information for your module. While you can enter this path in a relative way using the "./" prefix, we encourage you to define a macro on top of your build script for resolving the file system path. Further, you should also create a macro for your repository, e.g. <your repository name>.home, that you can use as a base path for resolving the file system location of your modules. By using macros for this purpose, you can overwrite their values from outside the build script when executing the ant script that gets generated from your MPS build script.

Next, in default layout, we describe the structure of our packaged artifacts. Inside our template, we configure the build to package our compiled plugin (yourplugin) inside a zip file (<your plugin.zip>). Finally, below this section, we configure via mps settings the headless MPS instance being used throughout the build. In this configuration, first, we enable bootstrapping allowing MPS to break up modules (solutions/languages) into multiple smaller chunks while running code generation and compilation. This option is used in case of cyclic dependencies, and is only relevant for code generation and compilation, it does not influence the layout of classes or packaging of plugins. It's good practice to leave this options disabled, because MPS will interrupt code generation for your build script with an error message, pointing you to cycles between your modules. Finally, both heap-related options at the bottom of this configuration are important, if you run into out of memory issues during code generation.

Build time Dependencies defined in build script template

Example Project

After describing the build script template in the section before, we now continue by discussing an example MPS project that we have built on top of the mbeddr platform. The complete source code for this example is located in the language module com.baselanguage.unless that is part of the mbeddr repository and can be found at the following file system location:

mbeddr.core
└─code
  └─applications
    └─com.mbeddr.build-examples

The notion behind this example is to illustrate based on an unless statement that we have written for MPS' base language how the previously described build script template is used for writing a real-world build script. To create an icon for the unless statement, we have used the language com.mbeddr.mpsutil.iconchar coming with the mbeddr platform. By using this language, we have introduced a dependency from our unless language to the mbeddr platform. The build script com.baselanguage.unless.build (shown in the screenshot below) for our language com.baselanguage.unless reflects this dependency and is based on the template build script for the mbeddr platform (platform-extension.template) that we have described before. In addition to content from the template, this build script contains a macro mbeddr.github.core.home that points to the repository root and specifies the value of artifacts.root to point to a folder artifacts located right underneath the repository root. Further, the script enriches the idea plugin from the template with additional information and contains a mps group com.baselanguage.unless that contains a lanuage com.baselanguage.unless, referring to the .mpl file via the macro mbeddr.github.core.home. Running code generation on the build solution will generate the ant script that we can directly invoke from the command-line.

Build script for the unless statement

After running code generation, we will find a generated build.xml representing an ant script at the following file system location:

mbeddr.core
└─build
  └─com.baselanguage.unless.build
    └─build.xml

We could now execute this script for packaging the plugin, however, we first of all need to retrieve the mbeddr platform (build time dependency) and a MPS release that we will use for building our plugin. For resolving both artifacts we use the gradle script, invoking it this way from the command line:

gradle -b download.gradle resolveMPS resolvePlatform

Afterwards, we will see the artifacts shown below on the file system of the mbeddr.core repository.

mbeddr.core
└─artifacts
  └─artifacts
    └─com.mbeddr.platform.distribution
      └─platform-distribution.zip
└─MPS

Next, remember, paths specified in macros will not be correct for your local machine, hence, we have to update them for your build environment. We don't do this inside the MPS build script, instead, we overwrite these values from the command-line, passing a set of arguments using the following syntax: -D<name>=<value>. In the snippet below, we do this for Dartifacts.root and mps.home, providing the path of the resolved MPS folder that is located inside the mbeddr.core repository (e.g., C:/repos/mbeddr.core/MPS). To execute the generated ant script, we invoke the targets clean, generate, and assemble. The following snippet shows the complete command being executed in the folder where the generated script is located:

ant -Dmps.home=<path to mbeddr.core repo>/MPS -Dartifacts.root=<path to mbeddr.core repo>/artifacts -f build.xml clean generate assemble

After running the build, we will find the packaged plugin (com.baselanguage.unless.zip) at the following file system location:

mbeddr.core
└─build
  └─com.baselanguage.unless.build
    └─build
      └─artifacts
        └─com.baselanguage.unless.build
          └─com.baselanguage.unless.zip

mbeddr

This section describes a template that we have created for illustrating how to setup a build depending on mbeddr. Further, we discuss for an example mbeddr C extension how to setup a build script by using this template.

Build Script Template

We have created a template illustrating how to setup a MPS build script for building a MPS project on top of mbeddr. This template is named mbeddr-extension.template and is shipped with the mbeddr allInOne distribution that can be found on the release page. If you use mbeddr from sources, you can find the template inside the the mbeddr build project that can be found here:

mbeddr.core
└─code
  └─languages
    └─com.mbeddr.build

This template declares on top (see screenshot below) a set of macros that we use for resolving paths during the build, e.g., mps.home refers to your MPS installation, artifacts.root points to a file system location where all of your dependencies, such as the mbeddr platform, will be located, finally, mbeddr.allInOne.artifacts refers to the location of the mbeddr distribution, a build artifact representing the compiled and packaged mbeddr release. We will later demonstrate how to overwrite the specified paths for mps.home and artifacts.root to fit your environment, please ignore the values of these macros for now.

Macros defined in build script template

Below the macros section is the dependencies section (see screenshot below) that defines through referenced build scripts a set of artifacts that have to be present at build time. In our template we define dependencies on mps, jetpad and mpsDiagramEditor, all three coming with MPS. Further, we use the previously described mps.home macro to resolve these artifacts from the MPS installation. You can specify artifact locations by typing an opening parenthesis behind the build script name. It's good practice to have such an artifact locations for each dependency. Besides MPS, we also define a dependency on the build script com.mbeddr.allInOne, which is responsible for packaging all plugins being shipped with mbeddr. This way, the build will resolve the mbeddr plugins as build dependencies.

Build time Dependencies defined in build script template

Below the dependencies section is the project structure that is used for configuring the build, describing plugin descriptors and listing all solutions and languages that should be built. On top of this section (see screenshot below), we have generator options being used for configuring the code generator with the same options that we use in mbeddr. Next, java options configures the Java compiler being used for compiling languages, and solutions containing Base Language code. Next, is a template for an idea plugin (see screenshot below) that contains dummy names, which you should replace with project-specific names. Each idea plugin ends up in an idea plugin descriptor, serialized to xml and packaged with the compiled plugin code. While these plugin descriptors specify a set of names, they additionally require a version number, optional vendor information, content referring to solutions and language described in same section and being packaged with the plugin. Finally, runtime dependencies lists other plugins that should be available in the MPS target environment where your plugin is deployed.

Below the idea plugin is a mps group <your solutions/languages group> that you can use for grouping languages and solutions that you want to build and package in a plugin. After copying the template, please change the group name accordingly to your project. Inside this group, you can either type the word language or solution on the cell containing the text <empty> to specify a module that you want to build with your build script. Next, you can specify in the load from section of your instantiated module a path to the .msd (solution) or .mpl (language) file that contains meta information for your module. While you can enter this path in a relative way using the "./" prefix, we encourage you to define a macro on top of your build script for resolving the file system path. Further, you should also create a macro for your repository, e.g. <your repository name>.home, that you can use as a base path for resolving the file system location of your modules. By using macros for this purpose, you can overwrite their values from outside the build script when executing the ant script that gets generated from your MPS build script.

Next, in default layout, we describe the structure of our packaged artifacts. Inside our template, we configure the build to package our compiled plugin (yourplugin) inside a zip file (<your plugin.zip>). Finally, below this section, we configure via mps settings the headless MPS instance being used throughout the build. In this configuration, first, we enable bootstrapping allowing MPS to break up modules (solutions/languages) into multiple smaller chunks while running code generation and compilation. This option is used in case of cyclic dependencies, and is only relevant for code generation and compilation, it does not influence the layout of classes or packaging of plugins. It's good practice to leave this options disabled, because MPS will interrupt code generation for your build script with an error message, pointing you to cycles between your modules. Finally, both heap-related options at the bottom of this configuration are important, if you run into out of memory issues during code generation.

Build time Dependencies defined in build script template

Build Scripts

mbeddr Release