-
Notifications
You must be signed in to change notification settings - Fork 9
Build
Ciera itself is built using Maven and it is used extensively to build other Ciera-based applications. Maven is an incredibly useful tool, but it can be frustrating if you do not understand it. I recommend taking a couple hours to read and learn the basics.
Ciera requires three things for a successful build:
-
An input model file with parsed OAL
-
A set of application marks (and feature specification)
-
An output location
The rest of the topics in this chapter will expound on how each of those three elements is configured and provided to the compiler.
First, Ciera requires clean, parsed model data with all proxies resolved, in a single file. This has historically been a task handled for model compilers by the BridgePoint tool itself. Ciera supports pre-built output from BridgePoint.
Ciera also supports ouptut from the pyxtuml pre-builder. pyxtuml is a
Python based dynamic xtUML tool used as the model backend by the pyrsl RSL
generator. Details about pyxtuml, its author and its history can be seen in
the pyxtuml documentation. Specific
details about the pre-builder feature can be seen in the
OAL
prebuilder section. Using pyxtuml allows Ciera to be free of build
dependencies on BridgePoint. Ciera projects can be built and executed entirely
on a system with no BridgePoint installation, making it much easier to
integrate into server builds.
The pyxtuml pre-builder is significantly faster for small-medium sized
projects, since it does not suffer the weight of Eclipse, however for very
large projects, the BridgePoint pre-builder is actually faster. It should also
be noted that the BridgePoint pre-builder remains the gold standard
implementation for OAL parsers.
The pyxtuml pre-builder is the preferred pre-build solution for Ciera projects
because of its light weight and portability, however it does introduces an
external dependency. pyxtuml must be installed on the system:
pip install pyxtuml
Let’s take a look at the pom.xml file for the MicrowaveOven example:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.ciera</groupId>
<artifactId>MicrowaveOven</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>runtime</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.ciera</groupId>
<artifactId>ciera-maven-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>pre-build</id>
<goals>
<goal>pyxtuml-pre-build</goal>
</goals>
</execution>
<execution>
<id>ciera-core</id>
<goals>
<goal>core</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>${project.basedir}</directory>
<filtering>true</filtering>
<includes>
<include>models/**/*.xtuml</include>
<include>.project</include>
</includes>
</resource>
<resource>
<directory>${project.build.directory}/generated-sources/java</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
</project>
Let’s break this down section by section:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.ciera</groupId>
<artifactId>MicrowaveOven</artifactId>
<packaging>jar</packaging>
<version>1.0.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
This is the basic setup for a Maven project. We have group and artifact identifers, packaging scheme, version identifier and some properties which define our character set and Java compiler version.
<dependencies>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>runtime</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
Next we have our dependency section. All Ciera-based projects depend on the Ciera runtime library included here. In this case, it is the only dependency.
<build>
<plugins>
<plugin>
<groupId>io.ciera</groupId>
<artifactId>ciera-maven-plugin</artifactId>
<version>2.1.0</version>
<executions>
<execution>
<id>pre-build</id>
<goals>
<goal>pyxtuml-pre-build</goal>
</goals>
</execution>
<execution>
<id>ciera-core</id>
<goals>
<goal>core</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
The first part of the build section defines that this project uses the
ciera-maven-plugin. This is the worker that actually handles the execution of
the compiler. There are two execution units that we make use of: the pre-build
and the core generation. The pre-build is done by pyxtuml and the core
generation is done by the core model compiler. Other projects might also have
executions for generating instance loaders/dumpers or template utilities. The
pre-build section can be used to configure the BridgePoint pre-builder if that
is preferred. See the ciera-maven-plugin
in detail section for more on BridgePoint pre-builder.
<resources>
<resource>
<directory>${project.basedir}</directory>
<filtering>true</filtering>
<includes>
<include>models/**/*.xtuml</include>
<include>.project</include>
</includes>
</resource>
This section is standard for Ciera-based projects. It simply indicates to maven
that all .xtuml files should be packaged into the output artifact (JAR). This
allows Ciera-based xtUML "library" projects to be distributed as dependencies.
See the next section for detail.
<resource>
<directory>${project.build.directory}/generated-sources/java</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
</project>
This final section is also standard for Ciera-based projects. It assues that
.properties files are included as resources in the output artifact. This is
used to store the version information for components.
Ciera leans into the dependency mechanism of Maven and therefore utilizes the Maven dependency mechanism to specify other xtUML projects that need to be included for inter-project references. A major problem with including other projects is dealing with fragile filesystem relative paths to locate model elements. Eclipse solves this using their workspace model (virtual filesystem) to bring all imported projects together. Ciera needs to be independent of BridgePoint and Eclipse.
The ciera-maven-plugin automatically invokes the pyxtuml pre-builder and
passes the path to artifacts listed as Maven dependencies. If an xtUML project
was built and installed in the local Maven repository or exists on an accessible
remote repository, it can be accessed and passed directly to pre-builder.
Consider the GPS Watch example:
<dependencies>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>runtime</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>HeartRateMonitor</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>Location</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>Tracking</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.ciera</groupId>
<artifactId>UI</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.googlecode.lanterna</groupId>
<artifactId>lanterna</artifactId>
<version>3.0.1</version>
</dependency>
</dependencies>
The GPS Watch example is comprised of five separate projects. Each has its own
pom.xml in which its .xtuml files are zipped up in the output JAR. The
system deployment project that is translated with Ciera declares Maven
dependencies on each of the four "library" projects and all of their xtUML
modeled elements are pulled in automatically to the pre-build.
I see a future in which a widely used data model like the mcooa project is
built with Maven and published and model compiler projects can easily access it
in this way without even needing the project on their machine much less in their
development folder.
(I see a further future where Ciera can reuse compiled implementations of components directly without re-translation, but that is not a reality now.)
Each of the "goals" the ciera-maven-plugin provides are documented below.
The pyxtuml pre-build goal takes input files and executes the pyxtuml
pre-build utility to produce clean SQL input for a Ciera compiler. It has the
following configuration parameters:
The location of the output SQL file. The default value is <project_name>.sql
in the project build directory (target/ is the default build directory for
Maven, but can be configured differently in the main build section of the
pom.xml file).
This list of directories to look for input models. This option is typically only used to specify model dependencies by path instead of included as a dependency (described above). This has some benefit in flexibility especially of required projects are not built with Maven, but suffers in its reliance on consistent filesystem paths. This method of including dependency models is not recommended.
If "true", models dependency artifacts are searched for model files. This is typically false if "modelDirs" is used. Default value is "true".
If "true", the models/ directory in the current project is searched for model
files. This is typically false only if "modelDirs" is being used. Default value
is "true".
Specifies the name/path of the Python executable to use for pyxtuml. The
default value is "python" which will execute the default Python interpreter
installed on
the system. This value can be changed to use an alternate interpreter. For
example, the Ciera projects themselves use the pypy interpreter because it
parses the OAL almost three times faster than standard CPython.
|
Note
|
If you use a different Python interpreter, you may need to install
pyxtuml again for that specific interpreter (e.g. pip3 install pyxtuml for
python3)
|
In addition to the MicrowaveOven example given above, consider the following
pom.xml snippet from the Ciera core model compiler.
<execution>
<id>pre-build</id>
<goals>
<goal>pyxtuml-pre-build</goal>
</goals>
<configuration>
<includeDependencyModels>false</includeDependencyModels>
<modelDirs>
<param>${project.basedir}/../runtime/models</param>
<param>${bpLoc}/src/org.xtuml.bp.ui.marking/models</param>
<param>${mcLoc}/model/mcooa/models</param>
</modelDirs>
</configuration>
</execution>
In this example, models are not included from the dependency list, but paths are specified in the configuration of the pre-build itself.
This is done because Ciera is built with itself, and as such, the Ciera runtime library it requires as a runtime dependency is not the same as the one it needs as a build dependency (self-building compilers are confusing!).
The BridgePoint pre-build goal uses the BridgePoint CLI to pre-build a project in a pre-defined Eclipse workspace. It requires that BridgePoint be installed and a workspace be set up, however it does not require a window manager (it can still be part of a server build).
The location of the BridgePoint installation. If no value for "bpHome" is specified, the build will fail.
The location of the BridgePoint workspace where the models are imported. The name of the Maven project is used to determine which project in the workspace to build. This implies that the name of the Maven project and the name of the BridgePoint project must match. If no value for "workspace" is specified, the build will fail. All models required for the build must be imported into the workspace including the Ciera runtime library. An easy way to check this is to run a "parse all" in the BridgePoint workspace and verify that there are no parse errors due to missing model elements.
The previous two options can be specified by environment variables BPHOME and WORKSPACE respecitively. This can be useful if you are working on multiple Ciera projects in the same workspace or if you prefer not to couple development workspace and tool paths with your project source code.
<execution>
<id>pre-build</id>
<goals>
<goal>bridgepoint-pre-build</goal>
</goals>
<configuration>
<bpHome>/Users/levi/xtuml/m6190.2019-12-18-1004_nightly-build/BridgePoint.app/Contents/Eclipse</bpHome>
<workspace>/var/folders/6n/ybm_82hn3wq4w972zjl90q9w0000gp/T/tmp.issCz64J</workspace>
</configuration>
</execution>
|
Note
|
Since BridgePoint manages the acutal pre-build, the location of the output
model file is determined by BridgePoint. You will have to refer to the
BridgePoint project to confirm what this location is. As of this writing,
BridgePoint outputs pre-built model files to
gen/code_generation/<project_name>.sql where <project_name> is the name of
the BridgePoint project.
|
The core goal is the main code generation tool. For most Ciera projects, one of the pre-build goals and the core goal are all that is necessary to build the project.
The location of the input pre-built model file for translation. The default
value is the same as the default outputFile of the pyxtuml pre-build goal.
The location of an output file where instances of OOA of OOA and Ciera architectural models will be dumped. The default value is an empty string (which causes the compiler to skip dumping output). This option is used if there is a downstream compiler that you need to load the instance population to generate additional Java source files.
The location where the generated Java source will be output. The default value
is generated-sources/java in the project build directory.
The SQL goal generates a SQL insert statement loader/dumper for the model. For
more information, see the Persistence chapter. The
configuration parameters are identical to the core goal.
The template goal parses a set of RSL templates and generates a template
registry. It also processes RSL substitutions in literal strings within OAL. For
more information, see the Templating chapter. The configuration
parameters are identical to the core goal.
Although it is not recommended, Ciera is not strictly dependent on Maven. This section will demonstrate step by step how to download the Ciera artifacts, build and run the MicrowaveOven example project.
The Ciera runtime library and core generation tool are needed. Download directly from Maven central with:
wget https://search.maven.org/remotecontent?filepath=io/ciera/runtime/2.1.0/runtime-2.1.0.jar -O runtime.jar wget https://search.maven.org/remotecontent?filepath=io/ciera/tool-core/2.1.0/tool-core-2.1.0.jar -O core.jar wget https://search.maven.org/remotecontent?filepath=org/antlr/antlr4-runtime/4.7.1/antlr4-runtime-4.7.1.jar -O antlr.jar
Pre-build the model with:
python -m bridgepoint.prebuild -o MicrowaveOven.sql runtime.jar models/
Alternatively, import the project into a BridgePoint workspace and import
existing projects from the runtime.jar archive and run a pre-build within
BridgePoint.
Generate Java source with:
mkdir src-gen java -cp runtime.jar:antlr.jar:core.jar io.ciera.tool.CoreTool -i MicrowaveOven.sql --gendir src-gen --cwd .
Compile Java with:
find src-gen/ -name *.java > sources.txt javac -cp runtime.jar -d bin @sources.txt
As demonstrated above, it is possible to use Ciera without Maven — in fact, the
Ciera compiler itself is only a small piece in a longer build chain including
pre-build, generation, compilation, and execution. The code generator has its
own command line interface and Maven simply maps configuration from the
pom.xml file to existing CLI options.
The following is the output of passing -h to the Ciera tool:
$ java -cp runtime.jar:antlr.jar:core.jar io.ciera.tool.CoreTool -h Usage: --cwd <root_dir> : base working directory --gendir <gen_dir> : generated output directory -i <input_file> : input file -o <output_file> : output file --use-version <use_version> : version identifier for generated components -h, --help : Print usage information.
When running projects generated with Ciera, in addition to the the compiled Java classes, some libraries must be in the classpath.
-
For all Ciera generated projects, the Ciera runtime library must be in the classpath. In general, the runtime library must have the same major version as the version of the code generation tool used to generate the code (for more details on the Maven versioning policy, see Maven version number policy).
-
For projects using JSON serialization for message passing, the JSON library found here is required.
-
For projects using SQL instance loading, the Antlr 4.7.1 runtime library is required.
-
Any other external libraries referenced in hand written code must be on the classpath.
If you are using Maven as your build tool, all of these dependencies will be downloaded in your local Maven repository which is a nice consistent place to reference them. The Ciera example projects each have a "run" bash script which builds the classpaths from the JARs installed in the local Maven repository.
Release versions of Ciera will be published to the Maven central repository. This is the default repository for Maven and artifacts hosted here will be downloaded automatically with no extra configuration.
Snapshot versions of Ciera (i.e. development versions/nightly builds) are hosted
in the Sonatype snapshot repository. To access development versions of Ciera,
you must add the following <repository> and <pluginRepository> definitions
in your project pom.xml or in your Maven settings.xml. More information on
declaring additional repositories can be found
here.
<repository> <id>snapshot-repo</id> <url>http://oss.sonatype.org/content/repositories/snapshots</url> <releases><enabled>false</enabled></releases> <snapshots><enabled>true</enabled></snapshots> </repository>
<pluginRepository> <id>snapshot-repo</id> <url>http://oss.sonatype.org/content/repositories/snapshots</url> <releases><enabled>false</enabled></releases> <snapshots><enabled>true</enabled></snapshots> </pluginRepository>