It builds the mason binary so that the command line interface can be used.
This installs mason in the same place as the chapel compiler (chpl) so that
mason can be used anywhere in the user's file system.

The first file listed is the Mason.toml. This is the manifest file
for the package. All dependencies for the package are listed in this file
as well as additional metadata about the package.

The src/ folder is where the source code of the package should reside.
As you might expect, the test/ folder and the example folder hold
tests and examples for your package, respectively. We will get to the
additional functionality that comes with these folders later.

Mason enforces that the main file be named after the package to enforce namespacing.
MyPackage.chpl will be the first file listed in src/.

As you can see, new files have been added to the package, the first of which
is the Mason.lock. You can think of this file as a snapshot of a single
run of the program. This file "locks" in the settings in which the program
ran upon invocation of masonrun. This file can be generated manually
with the masonupdate command. masonupdate will read the Mason.toml,
resolve dependencies, and generate the Mason.lock based on it's contents.

The target/ directory is where Mason stores all the binaries related to your package.
These could be binaries for the main source code as well as examples and tests. There are two types of
targets for building. The default location of a package binary is target/debug/, as shown in the
example above. However, if a final version of an application or library is
being produced, the --release flag can be thrown as follows:

mason run --build --release --force

The --release option adds the --fast argument to the compilation step.

The argument --force is included as Mason will only build the package if
the package has been modified. Throwing the --release flag will result in
the following package structure:

As you can see there are now two binaries of MyPackage, one under debug/ and
one under release. To remove the target/ directory along with all of the binaries
for your package, use the masonclean command.

For packages that span multiple files, the main module is designated by the module that
shares the name with the package directory and the name field in the Mason.toml.

For packages that span multiple sub-directories within src, sub-directories must be passed
to Mason with the -M<src/subdirectory> flag which is forwarded to the chapel compiler. For example, lets say
MyPackage's structure is as follows:

For an example of forwarding arguments in a call to masonrun, a chapel program built in
mason might have a configconstnumber that corresponds to a value used in MyPackage.chpl.
To try out different values at runtime, pass the values for number to masonrun as follows:

mason run --number=100
mason run --number=1000

Note

For the case when a flag intended for the chpl compiler or executable is recognized by
masonbuild or masonrun, respectively, the flag can be thrown after --
to override this conflict. For example, masonrun---nl4. Instead of mason recognizing
this argument, this command will run the executable over 4 locales.

Mason testing is based on exit code which means that if the package's tests compile
and run successfully, despite the "result" of the program, the tests pass. For this
reason, Mason users should configure their tests such that a failure produces an
exit code other than 0. Using exit() is the easiest way to do this, but throwing
errors is another way to accomplish the same thing.

To run the test(s), use the command masontest. If tests are not explicitly specified in Mason.toml,
Mason will gather all the tests found in test/, compile them with the dependencies listed in your Mason.toml
and run them producing the following output:

Mason supports examples as a way to demonstrate typical usage of a package.
The following example adds an example to MyPackage and runs it.
The example below prints a message a number of times based on the configconstcount:

configconstcount:int=10;foriin1..count{writeln("This is an example!!");}

To build the example without running it, use the command masonbuild--example.
This command will build ALL examples found either in the example/ directory or
listed in the Mason.toml

Note

If examples or tests are listed in the Mason.toml, Mason will not search
for any examples or tests not listed.

To view what examples are available, enter masonrun--example without any other
arguments. This will produce the names of all examples that are currently available
to Mason:

Examples can either be specified in the Mason.toml, or found automatically by Mason. However,
to include compile time or runtime arguments for examples, users must explicitly declare them
in their Mason.toml as follows:

Creating a website for package documentation is a breeze with Mason. Mason uses chpldoc which turns any .chpl file
into Sphinx documentation. To document a package, run the command masondoc while inside of a package. The
documentation will be automatically generated as long as chpldoc has been set up. For instructions on how to set up
chpldoc, view its documentation. Documentation will be built into the doc/ folder that will be created upon
the first call of masondoc.

Mason allows for specification of external, non-Chapel dependencies through two
mediums, Spack and pkg-config. The following two sections document how to
use masonexternal and masonsystem to interface with Spack and pkg-config
packages respectively.

System dependencies are packages that are found on your system through pkg-config. To use
this functionality of Mason, users must have pkg-config installed.

Mason interfaces with pkg-config through the masonsystem command.

masonsystemsearch will print all the current packages installed and available for use in a Mason package. To examine
the .pc file of a particular package, use masonsystempc<package> where <package>
is replaced with the particular package you are looking for. Here is an example of a workflow
for creating a Mason package with openssl which has already been installed.

First, search to see that it is installed with masonsystemsearchopenSSl which outputs:

Mason users can interface with Spack, a package manager geared towards high performance
computing. Through this integration, Mason user's now have
access to a large ecosystem of packages.
Non-destructive installs, custom version and configurations, and simple package installation
and uninstallation are a few of the features Mason gains through this integration.

Mason users can access Spack through the masonexternal command. Spack provides Mason users with the ability
to install and use any package in the Spack registry.
This interface is analogous to the previous example except when a package is missing, user's can download that package
through the Spack integration. The following is a workflow of finding, installing, and adding a Spack dependency to a Mason Package.

First, the Spack backend must be installed:

mason external --setup

This command will install Spack and set it up so that it can be used easily through Mason.

Let's use openSSL as an example since we used it in the system example. masonexternalsearchopenSSL
will search for the package and produce the following output:

$ mason external search openSSL
==> 2 packages.
openssl r-openssl

Obviously there are two types of the package listed, so we need to figure out which one to use.
To find out more about a package, use masonexternalinfo<package> as follows:

The correct package has been found, but not yet installed. Let's fix that.
We know that we want the preferred version which is 1.0.2k.
The command to install openssl version 1.0.2k would be:

mason external install openssl

Since the version was left out, version 1.0.2k is used because Mason
will always take the preferred version. This is a case where Spack's
spec expression syntax can be used to specify exactly which package is desired.
For example, other ways to install openSSL would be:

mason external install openssl@1.0.2k

which simply specifies the exact version that we want.
If we wanted to specify which compiler the package was built with:

mason external install openssl@1.0.2k%gcc

Mason will infer which compiler, in the case that the compiler is left out of the spec,
by looking at the environment variable CHPL_TARGET_COMPILER. For more information on
how to use spec expressions, use the command masonexternal--spec which would output the following:

As shown, Mason not only goes and gets the package specified, but also all of the dependencies
of the package specified. Packages are installed into unique directories such that it is impossible for package namespaces to collide.
Each dependency is downloaded distinctly for a package so no previous installs will be broken by installing new packages.
This way, multiple versions and builds of a package can be installed on a system and used without breaking anything.

Now that the correct package is installed, add it to the Mason.toml as follows:

Each versioned manifest file is identical to the manifest file in the top-level directory
of the package repository, with the exception of a file path or URL pointing to the repository and revision
in which the version is located.

Continuing the example from before, the 'registry' 0.1.0.toml would include the additional source field:

Search the registry with masonsearch<query>, which will list all packages
(and their latest version) that contain <query> in their names (case-insensitive).
If no query is provided, all packages in the registry will be listed.

Note

Packages will be listed regardless of their chplVersion compatibility.

The mason registry will hold the manifest files for packages submitted by developers.
To contribute a package to the mason-registry a chapel developer will need to host their
package and submit a pull request to the mason-registry with the toml file pointing
to their package. For a more detailed description follow the steps below.

Steps:

Write a library or binary package in chapel using mason

Host that package in a git repository. (e.g. GitHub)

Create a tag of your package that corresponds to the version number prefixed with a 'v'. (e.g. v0.1.0)

Fork the mason-registry on GitHub

Create a branch of the mason-registry and add your package's Mason.toml under Bricks/<package_name>/<version>.toml

Add a source field to your <version>.toml pointing to your package's repository.

Open a PR in the mason-registry for your newly created branch containing just your <version>.toml.

Wait for mason-registry gatekeepers to approve the PR.

Once your package is uploaded, maintain the integrity of your package, and please notify the
chapel team if your package should be taken down.

It is sometimes desirable to use a local registry, for example with libraries
you don't intend to distribute. The following steps create a local registry
starting with Bricks for PackageA and PackageB which were created with
masonnewPackageA and masonnewPackageB, and are located at
/path/to/my/packages/Package[AB]. It is expected that mason will be
extended to simplify and handle more of this process.

First create, commit, and tag the packages that will be in the registry:

The Mason.toml manifest file is written in TOML(for more information see TOML section below).
Each time a new package is created in Mason a standard TOML file is included in the top-level
directory of the package.

Mason can be configured by setting the following environment variables:

MASON_HOME : Path to a directory where mason will store cached registry
and package data. Defaults to $HOME/.mason.

MASON_REGISTRY : A comma separated list of name|location pairs, where
name is a local name for the registry at location. Defaults to
mason-registry|https://github.com/chapel-lang/mason-registry. If the
name| part of a pair is omitted it is inferred to be the word following
the final slash in location with any .git suffix removed.

The masonenv command will print the inferred or set values of these
environment variables. If a variable was set by the user, an asterisk will be
printed at the end of the line. For example, if $MASON_HOME was set:

TOML is the configuration language chosen by the chapel team for
configuring programs written in chapel. A TOML file contains the
necessary information to build a chapel program using mason.
TOML Spec.

To assist version resolution, the mason registry will enforce the following conventions:

The format for all versions will be a.b.c.

Major versions are denoted by a.
Minor versions are denoted by b.
Bug fixes are denoted by c.

If the major version is 0, no further conventions will be enforced.

The major version must be advanced if and only if the update causes breaking API changes,
such as updated data structures or removed methods and procedures. The minor and bug fix
versions will be zeroed out. (ex. 1.13.1 -> 2.0.0)

The minor version must be advanced if and only if the update adds functionality to the API
while maintaining backward compatibility with the current major version. The bug fix
version will be zeroed out. (ex. 1.13.1 -> 1.14.0)

The bug fix must be advanced for any update correcting functionality within a minor revision.
(ex. 1.13.1 -> 1.13.2)

The lock file Mason.lock is generated after running a masonupdate command. The user should
never manually edit the lock file as it is intended to "lock" in the settings of a certain
package build iteration. Mason.lock is added by default to the .gitignore when a new package
is created. If your intention is to create a binary application package that does not need to
be re-compiled by mason then take the Mason.lock out of your .gitignore. An example of
a lock file is written below as if generated from the earlier example of a Mason.toml: