MoonBit's Build System Tutorial
Moon is the build system for the MoonBit language, currently based on the n2 project. Moon supports parallel and incremental builds. Additionally, moon also supports managing and building third-party packages on mooncakes.io
Prerequisites
Before you begin with this tutorial, make sure you have installed the following:
-
MoonBit CLI Tools: Download it from the https://www.moonbitlang.com/download/. This command line tool is needed for creating and managing MoonBit projects.
Use
moon help
to view the usage instructions.$ moon help ...
-
MoonBit Language plugin in Visual Studio Code: You can install it from the VS Code marketplace. This plugin provides a rich development environment for MoonBit, including functionalities like syntax highlighting, code completion, and more.
Once you have these prerequisites fulfilled, let's start by creating a new MoonBit module.
Creating a New Module
To create a new module, enter the moon new
command in the terminal, and you will see the module creation wizard. By using all the default values, you can create a new module named username/hello
in the my-project
directory.
$ moon new
Enter the path to create the project (. for current directory): my-project
Select the create mode: exec
Enter your username: username
Enter your project name: hello
Enter your license: Apache-2.0
Created my-project
If you want use all default values, you can use
moon new my-project
to create a new module namedusername/hello
in themy-project
directory.
Understanding the Module Directory Structure
After creating the new module, your directory structure should resemble the following:
my-project
├── LICENSE
├── README.md
├── moon.mod.json
└── src
├── lib
│ ├── hello.mbt
│ ├── hello_test.mbt
│ └── moon.pkg.json
└── main
├── main.mbt
└── moon.pkg.json
Here's a brief explanation of the directory structure:
-
moon.mod.json
is used to identify a directory as a MoonBit module. It contains the module's metadata, such as the module name, version, etc.source
specifies the source directory of the module. The default value issrc
.{ "name": "username/hello", "version": "0.1.0", "readme": "README.md", "repository": "", "license": "Apache-2.0", "keywords": [], "description": "", "source": "src" }
-
lib
andmain
directories: These are the packages within the module. Each package can contain multiple.mbt
files, which are the source code files for the MoonBit language. However, regardless of how many.mbt
files a package has, they all share a commonmoon.pkg.json
file.lib/*_test.mbt
are separate test files in thelib
package, these files are for blackbox test, so private members of thelib
package cannot be accessed directly. -
moon.pkg.json
is package descriptor. It defines the properties of the package, such as whether it is the main package and the packages it imports.-
main/moon.pkg.json
:{ "is_main": true, "import": [ "username/hello/lib" ] }
Here,
"is_main: true"
declares that the package needs to be linked by the build system into a wasm file.-
lib/moon.pkg.json
:{}
This file is empty. Its purpose is simply to inform the build system that this folder is a package.
-
Working with Packages
Our username/hello
module contains two packages: username/hello/lib
and username/hello/main
.
The username/hello/lib
package contains hello.mbt
and hello_test.mbt
files:
hello.mbt
pub fn hello() -> String {
"Hello, world!"
}
hello_test.mbt
test "hello" {
if @lib.hello() != "Hello, world!" {
fail!("@lib.hello() != \"Hello, world!\"")
}
}
The username/hello/main
package contains a main.mbt
file:
fn main {
println(@lib.hello())
}
To execute the program, specify the file system's path to the username/hello/main
package in the moon run
command:
$ moon run ./src/main
Hello, world!
You can also omit ./
$ moon run src/main
Hello, world!
You can test using the moon test
command:
$ moon test
Total tests: 1, passed: 1, failed: 0.
Package Importing
In the MoonBit's build system, a module's name is used to reference its internal packages.
To import the username/hello/lib
package in src/main/main.mbt
, you need to specify it in src/main/moon.pkg.json
:
{
"is_main": true,
"import": [
"username/hello/lib"
]
}
Here, username/hello/lib
specifies importing the username/hello/lib
package from the username/hello
module, so you can use @lib.hello()
in main/main.mbt
.
Note that the package name imported in src/main/moon.pkg.json
is username/hello/lib
, and @lib
is used to refer to this package in src/main/main.mbt
. The import here actually generates a default alias for the package name username/hello/lib
. In the following sections, you will learn how to customize the alias for a package.
Creating and Using a New Package
First, create a new directory named fib
under lib
:
mkdir src/lib/fib
Now, you can create new files under src/lib/fib
:
a.mbt
:
pub fn fib(n : Int) -> Int {
match n {
0 => 0
1 => 1
_ => fib(n - 1) + fib(n - 2)
}
}
b.mbt
:
pub fn fib2(num : Int) -> Int {
fn aux(n, acc1, acc2) {
match n {
0 => acc1
1 => acc2
_ => aux(n - 1, acc2, acc1 + acc2)
}
}
aux(num, 0, 1)
}
moon.pkg.json
:
{}
After creating these files, your directory structure should look like this:
my-project
├── LICENSE
├── README.md
├── moon.mod.json
└── src
├── lib
│ ├── fib
│ │ ├── a.mbt
│ │ ├── b.mbt
│ │ └── moon.pkg.json
│ ├── hello.mbt
│ ├── hello_test.mbt
│ └── moon.pkg.json
└── main
├── main.mbt
└── moon.pkg.json
In the src/main/moon.pkg.json
file, import the username/hello/lib/fib
package and customize its alias to my_awesome_fibonacci
:
{
"is_main": true,
"import": [
"username/hello/lib",
{
"path": "username/hello/lib/fib",
"alias": "my_awesome_fibonacci"
}
]
}
This line imports the fib
package, which is part of the lib
package in the hello
module. After doing this, you can use the fib
package in main/main.mbt
. Replace the file content of main/main.mbt
to:
fn main {
let a = @my_awesome_fibonacci.fib(10)
let b = @my_awesome_fibonacci.fib2(11)
println("fib(10) = \{a}, fib(11) = \{b}")
println(@lib.hello())
}
To execute your program, specify the path to the main
package:
$ moon run ./src/main
fib(10) = 55, fib(11) = 89
Hello, world!
Adding Tests
Let's add some tests to verify our fib implementation. Add the following content in src/lib/fib/a.mbt
:
src/lib/fib/a.mbt
test {
assert_eq!(fib(1), 1)
assert_eq!(fib(2), 1)
assert_eq!(fib(3), 2)
assert_eq!(fib(4), 3)
assert_eq!(fib(5), 5)
}
This code tests the first five terms of the Fibonacci sequence. test { ... }
defines an inline test block. The code inside an inline test block is executed in test mode.
Inline test blocks are discarded in non-test compilation modes (moon build
and moon run
), so they won't cause the generated code size to bloat.
Stand-alone test files for blackbox tests
Besides inline tests, MoonBit also supports stand-alone test files. Source files ending in _test.mbt
are considered test files for blackbox tests. For example, inside the src/lib/fib
directory, create a file named fib_test.mbt
and paste the following code:
src/lib/fib/fib_test.mbt
test {
assert_eq!(@fib.fib(1), 1)
assert_eq!(@fib.fib2(2), 1)
assert_eq!(@fib.fib(3), 2)
assert_eq!(@fib.fib2(4), 3)
assert_eq!(@fib.fib(5), 5)
}
Notice that the test code uses @fib
to refer to the username/hello/lib/fib
package. The build system automatically creates a new package for blackbox tests by using the files that end with _test.mbt
. This new package will import the current package automatically, allowing you to use @lib
in the test code.
Finally, use the moon test
command, which scans the entire project, identifies, and runs all inline tests as well as files ending with _test.mbt
. If everything is normal, you will see:
$ moon test
Total tests: 3, passed: 3, failed: 0.
$ moon test -v
test username/hello/lib/hello_test.mbt::hello ok
test username/hello/lib/fib/a.mbt::0 ok
test username/hello/lib/fib/fib_test.mbt::0 ok
Total tests: 3, passed: 3, failed: 0.
Command-Line Help for moon
This document contains the help content for the moon
command-line program.
Command Overview:
moon
↴moon new
↴moon build
↴moon check
↴moon run
↴moon test
↴moon clean
↴moon fmt
↴moon doc
↴moon info
↴moon add
↴moon remove
↴moon install
↴moon tree
↴moon login
↴moon register
↴moon publish
↴moon package
↴moon update
↴moon coverage
↴moon coverage report
↴moon coverage clean
↴moon generate-build-matrix
↴moon upgrade
↴moon shell-completion
↴moon version
↴
moon
Usage: moon <COMMAND>
Subcommands:
new
— Create a new MoonBit modulebuild
— Build the current packagecheck
— Check the current package, but don't build object filesrun
— Run a main packagetest
— Test the current packageclean
— Remove the target directoryfmt
— Format source codedoc
— Generate documentationinfo
— Generate public interface (.mbti
) files for all packages in the moduleadd
— Add a dependencyremove
— Remove a dependencyinstall
— Install dependenciestree
— Display the dependency treelogin
— Log in to your accountregister
— Register an account at mooncakes.iopublish
— Publish the current modulepackage
— Package the current moduleupdate
— Update the package registry indexcoverage
— Code coverage utilitiesgenerate-build-matrix
— Generate build matrix for benchmarking (legacy feature)upgrade
— Upgrade toolchainsshell-completion
— Generate shell completion for bash/elvish/fish/pwsh/zsh to stdoutversion
— Print version information and exit
moon new
Create a new MoonBit module
Usage: moon new [OPTIONS] [PACKAGE_NAME]
Arguments:
<PACKAGE_NAME>
— The name of the package
Options:
-
--lib
— Create a library package instead of an executable -
--path <PATH>
— Output path of the package -
--user <USER>
— The user name of the package -
--name <NAME>
— The name part of the package -
--license <LICENSE>
— The license of the packageDefault value:
Apache-2.0
-
--no-license
— Do not set a license for the package
moon build
Build the current package
Usage: moon build [OPTIONS]
Options:
-
--std
— Enable the standard library (default) -
--nostd
— Disable the standard library -
-g
,--debug
— Emit debug information -
--release
— Compile in release mode -
--target <TARGET>
— Select output targetPossible values:
wasm
,wasm-gc
,js
,native
,all
-
--serial
— Handle the selected targets sequentially -
--enable-coverage
— Enable coverage instrumentation -
--sort-input
— Sort input files -
--output-wat
— Output WAT instead of WASM -
-d
,--deny-warn
— Treat all warnings as errors -
--no-render
— Don't render diagnostics from moonc (don't pass '-error-format json' to moonc) -
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date -
-w
,--watch
— Monitor the file system and automatically build artifacts
moon check
Check the current package, but don't build object files
Usage: moon check [OPTIONS]
Options:
-
--std
— Enable the standard library (default) -
--nostd
— Disable the standard library -
-g
,--debug
— Emit debug information -
--release
— Compile in release mode -
--target <TARGET>
— Select output targetPossible values:
wasm
,wasm-gc
,js
,native
,all
-
--serial
— Handle the selected targets sequentially -
--enable-coverage
— Enable coverage instrumentation -
--sort-input
— Sort input files -
--output-wat
— Output WAT instead of WASM -
-d
,--deny-warn
— Treat all warnings as errors -
--no-render
— Don't render diagnostics from moonc (don't pass '-error-format json' to moonc) -
--output-json
— Output in json format -
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date -
-w
,--watch
— Monitor the file system and automatically check files
moon run
Run a main package
Usage: moon run [OPTIONS] <PACKAGE_OR_MBT_FILE> [ARGS]...
Arguments:
<PACKAGE_OR_MBT_FILE>
— The package or .mbt file to run<ARGS>
— The arguments provided to the program to be run
Options:
-
--std
— Enable the standard library (default) -
--nostd
— Disable the standard library -
-g
,--debug
— Emit debug information -
--release
— Compile in release mode -
--target <TARGET>
— Select output targetPossible values:
wasm
,wasm-gc
,js
,native
,all
-
--serial
— Handle the selected targets sequentially -
--enable-coverage
— Enable coverage instrumentation -
--sort-input
— Sort input files -
--output-wat
— Output WAT instead of WASM -
-d
,--deny-warn
— Treat all warnings as errors -
--no-render
— Don't render diagnostics from moonc (don't pass '-error-format json' to moonc) -
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date -
--build-only
— Only build, do not run the code
moon test
Test the current package
Usage: moon test [OPTIONS]
Options:
-
--std
— Enable the standard library (default) -
--nostd
— Disable the standard library -
-g
,--debug
— Emit debug information -
--release
— Compile in release mode -
--target <TARGET>
— Select output targetPossible values:
wasm
,wasm-gc
,js
,native
,all
-
--serial
— Handle the selected targets sequentially -
--enable-coverage
— Enable coverage instrumentation -
--sort-input
— Sort input files -
--output-wat
— Output WAT instead of WASM -
-d
,--deny-warn
— Treat all warnings as errors -
--no-render
— Don't render diagnostics from moonc (don't pass '-error-format json' to moonc) -
-p
,--package <PACKAGE>
— Run test in the specified package -
-f
,--file <FILE>
— Run test in the specified file. Only valid when--package
is also specified -
-i
,--index <INDEX>
— Run only the index-th test in the file. Only valid when--file
is also specified -
-u
,--update
— Update the test snapshot -
-l
,--limit <LIMIT>
— Limit of expect test update passes to run, in order to avoid infinite loopsDefault value:
256
-
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date -
--build-only
— Only build, do not run the tests -
--no-parallelize
— Run the tests in a target backend sequentially -
--test-failure-json
— Print failure message in JSON format
moon clean
Remove the target directory
Usage: moon clean
moon fmt
Format source code
Usage: moon fmt [OPTIONS]
Options:
--check
— Check only and don't change the source code--sort-input
— Sort input files
moon doc
Generate documentation
Usage: moon doc [OPTIONS]
Options:
-
--serve
— Start a web server to serve the documentation -
-b
,--bind <BIND>
— The address of the serverDefault value:
127.0.0.1
-
-p
,--port <PORT>
— The port of the serverDefault value:
3000
-
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date
moon info
Generate public interface (.mbti
) files for all packages in the module
Usage: moon info [OPTIONS]
Options:
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date
moon add
Add a dependency
Usage: moon add <PACKAGE_PATH>
Arguments:
<PACKAGE_PATH>
— The package path to add
moon remove
Remove a dependency
Usage: moon remove <PACKAGE_PATH>
Arguments:
<PACKAGE_PATH>
— The package path to remove
moon install
Install dependencies
Usage: moon install
moon tree
Display the dependency tree
Usage: moon tree
moon login
Log in to your account
Usage: moon login
moon register
Register an account at mooncakes.io
Usage: moon register
moon publish
Publish the current module
Usage: moon publish [OPTIONS]
Options:
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date
moon package
Package the current module
Usage: moon package [OPTIONS]
Options:
--frozen
— Do not sync dependencies, assuming local dependencies are up-to-date--list
moon update
Update the package registry index
Usage: moon update
moon coverage
Code coverage utilities
Usage: moon coverage <COMMAND>
Subcommands:
report
— Generate code coverage reportclean
— Clean up coverage artifacts
moon coverage report
Generate code coverage report
Usage: moon coverage report [args]... [COMMAND]
Arguments:
<args>
— Arguments to pass to the coverage utility
Options:
-h
,--help
— Show help for the coverage utility
moon coverage clean
Clean up coverage artifacts
Usage: moon coverage clean
moon generate-build-matrix
Generate build matrix for benchmarking (legacy feature)
Usage: moon generate-build-matrix [OPTIONS] --output-dir <OUT_DIR>
Options:
-n <NUMBER>
— Set all ofdrow
,dcol
,mrow
,mcol
to the same value--drow <DIR_ROWS>
— Number of directory rows--dcol <DIR_COLS>
— Number of directory columns--mrow <MOD_ROWS>
— Number of module rows--mcol <MOD_COLS>
— Number of module columns-o
,--output-dir <OUT_DIR>
— The output directory
moon upgrade
Upgrade toolchains
Usage: moon upgrade [OPTIONS]
Options:
-f
,--force
— Force upgrade
moon shell-completion
Generate shell completion for bash/elvish/fish/pwsh/zsh to stdout
Usage: moon shell-completion [OPTIONS]
Discussion:
Enable tab completion for Bash, Elvish, Fish, Zsh, or PowerShell
The script is output on stdout
, allowing one to re-direct the
output to the file of their choosing. Where you place the file
will depend on which shell, and which operating system you are
using. Your particular configuration may also determine where
these scripts need to be placed.
The completion scripts won't update itself, so you may need to
periodically run this command to get the latest completions.
Or you may put `eval "$(moon shell-completion --shell <SHELL>)"`
in your shell's rc file to always load newest completions on startup.
Although it's considered not as efficient as having the completions
script installed.
Here are some common set ups for the three supported shells under
Unix and similar operating systems (such as GNU/Linux).
Bash:
Completion files are commonly stored in `/etc/bash_completion.d/` for
system-wide commands, but can be stored in
`~/.local/share/bash-completion/completions` for user-specific commands.
Run the command:
$ mkdir -p ~/.local/share/bash-completion/completions
$ moon shell-completion --shell bash >> ~/.local/share/bash-completion/completions/moon
This installs the completion script. You may have to log out and
log back in to your shell session for the changes to take effect.
Bash (macOS/Homebrew):
Homebrew stores bash completion files within the Homebrew directory.
With the `bash-completion` brew formula installed, run the command:
$ mkdir -p $(brew --prefix)/etc/bash_completion.d
$ moon shell-completion --shell bash > $(brew --prefix)/etc/bash_completion.d/moon.bash-completion
Fish:
Fish completion files are commonly stored in
`$HOME/.config/fish/completions`. Run the command:
$ mkdir -p ~/.config/fish/completions
$ moon shell-completion --shell fish > ~/.config/fish/completions/moon.fish
This installs the completion script. You may have to log out and
log back in to your shell session for the changes to take effect.
Elvish:
Elvish completions are commonly stored in a single `completers` module.
A typical module search path is `~/.config/elvish/lib`, and
running the command:
$ moon shell-completion --shell elvish >> ~/.config/elvish/lib/completers.elv
will install the completions script. Note that use `>>` (append)
instead of `>` (overwrite) to prevent overwriting the existing completions
for other commands. Then prepend your rc.elv with:
`use completers`
to load the `completers` module and enable completions.
Zsh:
ZSH completions are commonly stored in any directory listed in
your `$fpath` variable. To use these completions, you must either
add the generated script to one of those directories, or add your
own to this list.
Adding a custom directory is often the safest bet if you are
unsure of which directory to use. First create the directory; for
this example we'll create a hidden directory inside our `$HOME`
directory:
$ mkdir ~/.zfunc
Then add the following lines to your `.zshrc` just before
`compinit`:
fpath+=~/.zfunc
Now you can install the completions script using the following
command:
$ moon shell-completion --shell zsh > ~/.zfunc/_moon
You must then open a new zsh session, or simply run
$ . ~/.zshrc
for the new completions to take effect.
Custom locations:
Alternatively, you could save these files to the place of your
choosing, such as a custom directory inside your $HOME. Doing so
will require you to add the proper directives, such as `source`ing
inside your login script. Consult your shells documentation for
how to add such directives.
PowerShell:
The powershell completion scripts require PowerShell v5.0+ (which
comes with Windows 10, but can be downloaded separately for windows 7
or 8.1).
First, check if a profile has already been set
PS C:\> Test-Path $profile
If the above command returns `False` run the following
PS C:\> New-Item -path $profile -type file -force
Now open the file provided by `$profile` (if you used the
`New-Item` command it will be
`${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`
Next, we either save the completions file into our profile, or
into a separate file and source it inside our profile. To save the
completions into our profile simply use
PS C:\> moon shell-completion --shell powershell >>
${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
This discussion is taken from `rustup completions` command with some changes.
Options:
-
--shell <SHELL>
— The shell to generate completion forDefault value:
<your shell>
Possible values:
bash
,elvish
,fish
,powershell
,zsh
moon version
Print version information and exit
Usage: moon version [OPTIONS]
Options:
--all
— Print all version information--json
— Print version information in JSON format--no-path
— Do not print the path
This document was generated automatically by
clap-markdown
.
Module Configuration
moon uses the moon.mod.json
file to identify and describe a module.
Module Name
The name
field is used to specify the name of the module, and it is required.
{
"name": "example",
...
}
The module name can contain letters, numbers, _
, -
, and /
.
For modules published to mooncakes.io, the module name must begin with the username. For example:
{
"name": "moonbitlang/core",
...
}
Version
The version
field is used to specify the version of the module.
This field is optional. For modules published to mooncakes.io, the version number must follow the Semantic Versioning 2.0.0 specification.
{
"name": "example",
"version": "0.1.0",
...
}
Deps
The deps
field is used to specify the dependencies of the module.
It is automatically managed by commands like moon add
and moon remove
.
{
"name": "username/hello",
"deps": {
"moonbitlang/x": "0.4.6"
}
}
README
The readme
field is used to specify the path to the module's README file.
Repository
The repository
field is used to specify the URL of the module's repository.
License
The license
field is used to specify the license of the module. The license type must comply with the SPDX License List.
{
"license": "MIT"
}
Keywords
The keywords
field is used to specify the keywords for the module.
{
"keywords": ["example", "test"]
}
Description
The description
field is used to specify the description of the module.
{
"description": "This is a description of the module."
}
Source directory
The source
field is used to specify the source directory of the module.
It must be a subdirectory of the directory where the moon.mod.json
file is located and must be a relative path.
When creating a module using the moon new
command, a src
directory will be automatically generated, and the default value of the source
field will be src
.
{
"source": "src"
}
When the source
field does not exist, or its value is null
or an empty string ""
, it is equivalent to setting "source": "."
. This means that the source directory is the same as the directory where the moon.mod.json
file is located.
{
"source": null
}
{
"source": ""
}
{
"source": "."
}
Warning List
This is used to disable specific preset compiler warning numbers.
For example, in the following configuration, -2
disables the warning number 2 (Unused variable).
{
"warn-list": "-2",
}
You can use moonc build-package -warn-help
to see the list of preset compiler warning numbers.
$ moonc -v
v0.1.20240914+b541585d3
$ moonc build-package -warn-help
Available warnings:
1 Unused function.
2 Unused variable.
3 Unused type declaration.
4 Redundant case in a pattern matching (unused match case).
5 Unused function argument.
6 Unused constructor.
7 Unused module declaration.
8 Unused struct field.
10 Unused generic type variable.
11 Partial pattern matching.
12 Unreachable code.
13 Unresolved type variable.
14 Lowercase type name.
15 Unused mutability.
16 Parser inconsistency.
18 Useless loop expression.
19 Top-level declaration is not left aligned.
20 Invalid pragma
21 Some arguments of constructor are omitted in pattern.
22 Ambiguous block.
23 Useless try expression.
24 Useless error type.
26 Useless catch all.
A all warnings
Alert List
Disable user preset alerts.
{
"alert-list": "-alert_1-alert_2"
}
Package Configuration
moon uses the moon.pkg.json
file to identify and describe a package.
Name
The package name is not configurable; it is determined by the directory name of the package.
is-main
The is-main
field is used to specify whether a package needs to be linked into an executable file.
The output of the linking process depends on the backend. When this field is set to true
:
- For the
wasm
andwasm-gc
backends, a standalone WebAssembly module will be generated. - For the
js
backend, a standalone JavaScript file will be generated.
import
The import
field is used to specify other packages that a package depends on.
test-import
The test-import
field is used to specify other packages that the black-box test package of this package depends on.
wbtest-import
The wbtest-import
field is used to specify other packages that the white-box test package of this package depends on.
Link Options
By default, moon only links packages where is-main
is set to true
. If you need to link other packages, you can specify this with the link
option.
The link
option is used to specify link options, and its value can be either a boolean or an object.
-
When the
link
value istrue
, it indicates that the package should be linked. The output will vary depending on the backend specified during the build.{ "link": true }
-
When the
link
value is an object, it indicates that the package should be linked, and you can specify link options. For detailed configuration, please refer to the subpage for the corresponding backend.
wasm Backend Link Options
Configurable Options
-
The
exports
option is used to specify the function names exported by thewasm
backend.For example, in the following configuration, the
hello
function from the current package is exported as thehello
function in thewasm
module, and thefoo
function is exported as thebar
function in thewasm
module. In thewasm
host, thehello
andbar
functions can be called to invoke thehello
andfoo
functions from the current package.{ "link": { "wasm": { "exports": [ "hello", "foo:bar" ] } } }
-
The
heap-start-address
option is used to specify the starting address of the linear memory that can be used when compiling to thewasm
backend.For example, the following configuration sets the starting address of the linear memory to 1024.
{ "link": { "wasm": { "heap-start-address": 1024 } } }
-
The
import-memory
option is used to specify the linear memory imported by thewasm
module.For example, the following configuration specifies that the linear memory imported by the
wasm
module is thememory
variable from theenv
module.{ "link": { "wasm": { "import-memory": { "module": "env", "name": "memory" } } } }
-
The
export-memory-name
option is used to specify the name of the linear memory exported by thewasm
module.{ "link": { "wasm": { "export-memory-name": "memory" } } }
wasm-gc Backend Link Options
The link options for the wasm-gc
backend are similar to those for the wasm
backend, except there is no heap-start-address
option.
JS Backend Link Options
Configurable Options
-
The
exports
option is used to specify the function names to export in the JavaScript module.For example, in the following configuration, the
hello
function from the current package is exported as thehello
function in the JavaScript module. In the JavaScript host, thehello
function can be called to invoke thehello
function from the current package.{ "link": { "js": { "exports": [ "hello" ] } } }
-
The
format
option is used to specify the output format of the JavaScript module.The currently supported formats are:
esm
cjs
iife
For example, the following configuration sets the output format of the current package to ES Module.
{ "link": { "js": { "format": "esm" } } }
Warning List
This is used to disable specific preset compiler warning numbers.
For example, in the following configuration, -2
disables the warning number 2 (Unused variable).
{
"warn-list": "-2",
}
You can use moonc build-package -warn-help
to see the list of preset compiler warning numbers.
$ moonc -v
v0.1.20240914+b541585d3
$ moonc build-package -warn-help
Available warnings:
1 Unused function.
2 Unused variable.
3 Unused type declaration.
4 Redundant case in a pattern matching (unused match case).
5 Unused function argument.
6 Unused constructor.
7 Unused module declaration.
8 Unused struct field.
10 Unused generic type variable.
11 Partial pattern matching.
12 Unreachable code.
13 Unresolved type variable.
14 Lowercase type name.
15 Unused mutability.
16 Parser inconsistency.
18 Useless loop expression.
19 Top-level declaration is not left aligned.
20 Invalid pragma
21 Some arguments of constructor are omitted in pattern.
22 Ambiguous block.
23 Useless try expression.
24 Useless error type.
26 Useless catch all.
A all warnings
Alert List
Disable user preset alerts.
{
"alert-list": "-alert_1-alert_2"
}
Conditional Compilation
The smallest unit of conditional compilation is a file.
In a conditional compilation expression, three logical operators are supported: and
, or
, and not
, where the or
operator can be omitted.
For example, ["or", "wasm", "wasm-gc"]
can be simplified to ["wasm", "wasm-gc"]
.
Conditions in the expression can be categorized into backends and optimization levels:
- Backend conditions:
"wasm"
,"wasm-gc"
, and"js"
- Optimization level conditions:
"debug"
and"release"
Conditional expressions support nesting.
If a file is not listed in "targets"
, it will be compiled under all conditions by default.
Example:
{
"targets": {
"only_js.mbt": ["js"],
"only_wasm.mbt": ["wasm"],
"only_wasm_gc.mbt": ["wasm-gc"],
"all_wasm.mbt": ["wasm", "wasm-gc"],
"not_js.mbt": ["not", "js"],
"only_debug.mbt": ["debug"],
"js_and_release.mbt": ["and", ["js"], ["release"]],
"js_only_test.mbt": ["js"],
"js_or_wasm.mbt": ["js", "wasm"],
"wasm_release_or_js_debug.mbt": ["or", ["and", "wasm", "release"], ["and", "js", "debug"]]
}
}
Pre-build
The "pre-build"
field is used to specify pre-build commands, which will be executed before build commands such as moon check|build|test
.
"pre-build"
is an array, where each element is an object containing input
, output
, and command
fields. The input
and output
fields can be strings or arrays of strings, while the command
field is a string. In the command
, you can use any shell commands, as well as the $input
and $output
variables, which represent the input and output files, respectively. If these fields are arrays, they will be joined with spaces by default.
Currently, there is a built-in special command :embed
, which converts files into MoonBit source code. The --text
parameter is used to embed text files, and --binary
is used for binary files. --text
is the default and can be omitted. The --name
parameter is used to specify the generated variable name, with resource
being the default. The command is executed in the directory where the moon.pkg.json
file is located.
{
"pre-build": [
{
"input": "a.txt",
"output": "a.mbt",
"command": ":embed -i $input -o $output"
}
]
}
If the content of a.txt
in the current package directory is:
hello,
world
After running moon build
, the following a.mbt
file will be generated in the directory where the moon.pkg.json
is located:
let resource : String =
#|hello,
#|world
#|