Skip to content
DomenikP edited this page Aug 1, 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/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 three 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). This script declares two variables that specify file system locations where resolved artifacts should be copied to, both paths can be overwritten from outside when executing the script. Per default, the resolved MPS is downloaded to a folder <current directory>/mps (mpsLocation), whereas mbeddr and the mbeddr platform is downloaded to <current directory>artifacts (artifacstLocation).

mbeddr Platform

This section describes a template that we have created for illustrating how to setup a build script 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, which can either be downloaded from the release page or resolved via a gradle script. 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

The MPS Build Script guide explains parts that can be used in a MPS build script, specificly for this template, but also for the mbeddr build script template. Please read this guide before you continue reading.

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.

Plugin 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 build script is only used for building a solutions/languages, while we will later show in Scripts Generation Build Script Template a build script template to generate build scripts before execution. The template described in this section is named mbeddr-extension.template and is shipped with the mbeddr allInOne distribution , which can either be downloaded from the release page or resolved via a gradle script. 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

The MPS Build Script guide explains parts that can be used in a MPS build script, specificly for this template, but also for the mbeddr build script template. Please read this guide before you continue reading.

Scripts Generation Build Script Template

Example Project

Misc

MPS Build Scripts

Build scripts declare 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 will be located. In the screenshot below, we specify a macro platform.distribution.artifacts that refers to the location of the mbeddr platform distribution, a build artifact representing the compiled and packaged mbeddr platform release. In case you write a build script using the mbeddr template, then you will have a macro for the mbeddr build script, e.g., mbeddr.allInOne.artifacts.

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 templates 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 define in build scripts dependencies on build scripts that bundle plugins on which we base our languages or solutions. In case of the build script examples discussed in this guide, this is either com.mbeddr.platform.distribution or com.mbeddr.allInOne. The screenshot below demonstrates an example dependency on com.mbeddr.platform.distribution.

Build time Dependencies defined in build script template

The project structure 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 usually 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