MPS 2019.3 Help

HowTo -- MPS and ant

Working with MPS and ant

Editing code of course requires the MPS editor. But generating models and
running tests can be done from the command line to integrate it with automatic
builds. Ant is used as the basis. In this section we explain how to use MPS
from the command line via ant.

For all of the examples we use a build.properties file that defines the
following two properties:

mps.home = // installation directory of MPS itself mbeddr.home = // the root directory relative to which all other directories // to projects etc. are specified

This build.properties file is included in all the build scripts we discuss
in this section. In addition, we have to define a set of MPS-specific tasks
using the taskdef element in ant. Also, a couple of JVM options are reused
over and over. Consequently, the following is a skeleton of all the build files
we will discuss:

<project name="com.mbeddr.core build and test" default="all"> <property file="build.properties"/> <path id="mps.ant.path"> <pathelement location="${mps.home}/lib/mps-backend.jar"/> <pathelement location="${mps.home}/lib/jdom.jar"/> <pathelement location="${mps.home}/lib/log4j.jar"/> <pathelement location="${mps.home}/lib/mps-core.jar"/> </path> <taskdef resource="jetbrains/mps/build/ant/antlib.xml" classpathref="mps.ant.path"/> <jvmargs id="myargs"> <arg value="-ea"/> <arg value="-Xss1024k"/> <arg value="-Xmx1024m"/> <arg value="-XX:MaxPermSize=92m"/> <arg value="-XX:+HeapDumpOnOutOfMemoryError"/> </jvmargs> <!-- here is the place where all the following example code goes --> </project>

Building the Languages in a Project

We start by building the contents of a project. Here is the necessary ant code
that has to be surrounded by the skeleton ant file shown above:

<property name="project.mpr" value="relative/path/to/project/project.mpr"/> <target name="build-languages-in-project"> <mps.generate> <jvmargs refid="myargs"/> <project file="${mbeddr.home}/${project.mpr}"/> </mps.generate> </target>

All modules within the project are generated. If only a subset of the modules in
the project should be generated, a modules fileset can be used. The
following code generates all the languages in a project; typically they reside
in the languages directory below the project. Note how we define a
different property that points to the project directory as opposed to the
project .mps file.

<property name="project.mpr" value="relative/path/to/project/project.mpr"/> <property name="project.dir" value="relative/path/to/project"/> <mps.generate> <jvmargs refid="myargs"/> <project file="${mbeddr.home}/${project.mpr}"/> <modules dir="${mbeddr.home}/${project.dir}/languages"/> </mps.generate>

Sometimes a project needs access to other languages in order to be compilable.
These can be added with library elements, whose dir attribute has to
point to a directory that (directly, or further below) contains the required
languages.

<property name="some.other.project.dir" value="relative/p/to/other/project"/> <mps.generate> <jvmargs refid="myargs"/> <project file="${mbeddr.home}/${project.mpr}"/> <library name="irrelevantName" dir="${mbeddr.home}/${some.other.project.dir}/languages"/> </mps.generate>

Generating/Building Solutions

Building solutions that contain code written in a DSL is not fundamentally
different from building languages. However, it is important to set up the
libraries correctly so they point to the directories that contain the languages
used in the solutions.

<!-- project with solutions that should be built --> <property name="solutionproject.dir" value="path/to/some/solution/project"/> <!-- two projects that contain languages used by solutionproject --> <property name="langproject.dir" value="path/to/some/project"/> <property name="other.langproject.dir" value="path/to/other/project"/> <target name="build-solutions"> <mps.generate> <jvmargs refid="myargs"/> <!-- set up libs to point to the lang projects --> <library name="langproject" dir="${mbeddr.home}/${langproject.dir}"/> <library name="other.langproject" dir="${mbeddr.home}/${other.langproject.dir}"/> <!-- generate two solutions in the project --> <modules dir="${mbeddr.home}/${solutionproject.fit}/solutions/solution1"/> <modules dir="${mbeddr.home}/${solutionproject.fit}/solutions/solution2"/> </mps.generate> </target>

Running Tests

MPS supports a special testing language that can be used for testing
constraints, type system rules and editor functionality. These tests can be run
from the UI using the Run option from the solution or model context menu
(see the figure below).

runtests

These tests can also be run from the command line. Here is the code you need:

<!-- make this point to some temp directory --> <property name="mps.platform.caches" value="tmp"/> <!-- path to project .mpr with the tests in it --> <property name="project.mpr" value="relative/path/to/project/project.mpr"/> <target name="run-tests"> <delete dir="${mps.platform.caches}"/> <junit haltonfailure="true" showoutput="true" fork="true" dir="${mps.home}"> <jvmarg value="-ea"/> <jvmarg value="-Xss1024k"/> <jvmarg value="-Xmx1200m"/> <jvmarg value="-XX:MaxPermSize=128m"/> <jvmarg value="-XX:+HeapDumpOnOutOfMemoryError"/> <sysproperty key="idea.system.path" value="${mps.platform.caches}/system"/> <sysproperty key="idea.config.path" value="${mps.platform.caches}/config"/> <sysproperty key="idea.plugins.path" value="${mps.platform.caches}/plugins"/> <sysproperty key="mps.junit.project" value="${mbeddr.home}/${project.mpr}"/> <sysproperty key="mps.junit.pathmacro.mbeddr.home" value="${mbeddr.home}"/> <classpath> <fileset dir="${mps.home}/lib"> <include name="**/*.jar"/> </fileset> <fileset dir="${mps.home}/plugins"> <include name="**/*.jar"/> </fileset> </classpath> <test name="jetbrains.mps.testbench.junit.suites.DefaultTestSuite"/> <formatter type="xml"/> </junit> </target>

The important ingredients here are the two system properties
mps.junit.project and mps.junit.pathmacro.mbeddr.home. The first one
specifies the project that contains the tests. The second one is a bit more
involved. The syntax mps.junit.pathmacro.XXX sets a value for a path
variable XXX in an MPS project. To make the tests run correctly, there has
to be a TestInfo node in the project that points to the project file. This
one uses a path variable (defined in MPS settings) to make it portable between
different machines and various locations in the file system. The
mps.junit.pathmacro.mbeddr.home thingy is used to supply a value for the
macro from the command line.

testinfo

Last modified: 28 February 2020