Package Configuration#
moon uses a package file to identify and describe a package. The legacy format
is moon.pkg.json, and the new format is moon.pkg. For full JSON schema,
please check moon's repository.
New format (moon.pkg)#
The new format is a concise DSL. You can generate or reformat it from an
existing moon.pkg.json with:
moon fmt -C <module_dir>
Example:
import {
"moonbit-community/language/packages/virtual",
}
options(
"is-main": true,
overrides: [ "moonbit-community/language/packages/implement" ],
)
In moon.pkg, dependencies are declared in an import { ... } block. Use
@alias to set a custom alias:
import {
"moonbit-community/language/packages/pkgA",
"moonbit-community/language/packages/pkgC" @c,
"moonbitlang/core/builtin",
}
All other fields from moon.pkg.json move into a single options(...) block.
The key names and value shapes are unchanged; the legacy keys that contain - must be
quoted.
options(
"virtual": { "has-default": true },
)
The moon.pkg format allows comments //....
Full syntax of moon.pkg is as follows:
moon_pkg ::= statement*
statement ::= import | assign | apply
import ::= "import" "{" (import_item ",")* import_item? "}" import_kind?
import_item ::= STRING ("@" PKG_NAME)?
import_kind ::= "for" STRING
assign ::= LIDENT "=" expr
apply ::= LIDENT "(" (argument ",")* argument? ")"
argument ::= LIDENT ":" expr | STRING ":" expr
expr ::= array | object | apply | STRING | INT | "true" | "false"
array ::= "[" (expr ",")* expr? "]"
object ::= "{" (field ",")* field? "}"
Name#
The package name is not configurable; it is determined by the directory name of the package.
フォーマッタ#
formatter フィールドは、このパッケージに対する moon fmt の設定を行います。現在は、フォーマッタがスキップするファイル名の一覧である ignore をサポートしています。
これは、生成ファイルや、意図的に別の形式のままにしておきたいファイルに便利です。pre-build で生成されたファイルはすでに自動でスキップされるため、formatter.ignore は主に追加で除外したいファイルのために使います。
options(
formatter: {
ignore: [ "generated.mbt", "snapshot.mbt" ],
},
)
{
"formatter": {
"ignore": ["generated.mbt", "snapshot.mbt"]
}
}
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 and
wasm-gcbackends, a standalone WebAssembly module will be generated.For the
jsbackend, a standalone JavaScript file will be generated.
options(
"is-main": true,
)
{
"is-main": true
}
Importing dependencies#
Import#
The import field is used to specify other packages that a package depends on.
For example, the following imports pkgA and pkgC, aliasing pkgC to c.
User can write @c to access definitions from pkgC.
import {
"moonbit-community/language/packages/pkgA",
"moonbit-community/language/packages/pkgC" @c,
"moonbitlang/core/builtin",
}
{
"import": [
"moonbit-community/language/packages/pkgA",
{
"path": "moonbit-community/language/packages/pkgC",
"alias": "c"
},
"moonbitlang/core/builtin"
]
}
Most core packages are not special here: if you use @json, @test, or other
ordinary core aliases, add the corresponding moonbitlang/core/... package to
import to avoid core_package_not_imported warnings.
prelude is the exception. It is available by default, so the names it exposes
do not need an explicit package import.
Test import#
The test import is used to specify other packages that the black-box test package of this package depends on,
with the same format as import.
import {
"path/to/package1",
"path/to/package2" @pkg2,
} for "test"
{
"test-import": {
"path/to/package1",
{
"path": "path/to/package2",
"alias": "pkg2"
}
}
}
The test-import-all field is used to specify whether all public definitions from the package being tested should be imported (true) by default.
White-box test import#
The white-box test import is used to specify other packages that the white-box test package of this package depends on,
with the same format as import.
import {
"path/to/package1",
"path/to/package2" @pkg2,
} for "wbtest"
{
"wbtest-import": {
"path/to/package1",
{
"path": "path/to/package2",
"alias": "pkg2"
}
}
}
最大同時テスト数#
max-concurrent-tests フィールドは、moon test がこのパッケージを実行するときに、このパッケージのテストを同時に実行できる数を制限します。
同じパッケージ内のテストがポート、一時ファイル、または同時実行すべきでないその他の外部リソースを共有する場合に便利です。
options(
"max-concurrent-tests": 2,
)
{
"max-concurrent-tests": 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:
options(
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"]]
}
)
{
"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"]]
}
}
Supported Targets#
The supported-targets option declares which backends a package is intended to support.
It uses a target-set expression, not an array:
options(
"supported-targets": "js",
)
{
"supported-targets": "js"
}
Examples:
jsfor a single backend+js+wasm-gcfor an explicit set of backends+all-jsfor all backends exceptjs
Legacy array syntax is still accepted for compatibility:
{
"supported-targets": ["js", "native"]
}
This is package metadata, not a conditional compilation rule:
use
supported-targetsto declare the package's supported backend setuse
targetsto include or exclude individual files for different backendsuse
preferred-targetinmoon.mod.jsonto choose the default backend for commands such asmoon check,moon run, andmoon build
When both the module and the package declare supported-targets, the effective backend set is
their intersection.
Command behavior follows the selected backend:
moon check,moon build,moon test, andmoon benchkeep only packages that support the selected backendmoon runrequires the selected package to support the selected backendmoon infoskips unsupported selected packages with a warningmoon bundleskips package targets that do not support the selected backend
After root selection, Moon also checks reachable required dependencies. If a required dependency does not support the selected backend, the command fails with a normal user-facing error.
Notes:
omitting
supported-targetsmeans all backends are supported--target allexpands towasm,wasm-gc,js, andnative, but notllvmllvmis still a validsupported-targetsvaluelegacy array syntax is deprecated, but still accepted for compatibility
A common setup is:
mark a native-only package with
"supported-targets": "native"set
"preferred-target": "native"inmoon.mod.jsonuse
targetsonly when some files inside the package differ by backend
ネイティブスタブファイル#
native-stub フィールドは、native ビルド向けにこのパッケージと一緒にコンパイルすべき C スタブソースファイルを列挙します。
これは、FFI ドキュメントにある extern "C" 宣言 と組み合わせて使われることが多く、その場合スタブファイルは、MoonBit で直接書くより C で書く方が容易なラッパー関数やアダプタコードを提供します。
パスはパッケージディレクトリからの相対パスです。
options(
"native-stub": [ "stub.c", "helpers.c" ],
)
{
"native-stub": ["stub.c", "helpers.c"]
}
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.
現在、link は native バックエンドでは動作しません。この節で説明する挙動は wasm、wasm-gc、js バックエンドに適用されます。
When the
linkvalue istrue, it indicates that the package should be linked. The output will vary depending on the backend specified during the build.options( link: true )
{ "link": true }
When the
linkvalue 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#
Common Options#
The
exportsoption is used to specify the function names exported by the Wasm backend.For example, in the following configuration, the
hellofunction from the current package is exported as thehellofunction in the Wasm module, and thefoofunction is exported as thebarfunction in the Wasm module. In the Wasm host, thehelloandbarfunctions can be called to invoke thehelloandfoofunctions from the current package.options( link: { "wasm": { "exports": [ "hello", "foo:bar" ], }, "wasm-gc": { "exports": [ "hello", "foo:bar" ], } } )
{ "link": { "wasm": { "exports": [ "hello", "foo:bar" ] }, "wasm-gc": { "exports": [ "hello", "foo:bar" ] } } }
The
import-memoryoption is used to specify the linear memory imported by the Wasm module.For example, the following configuration specifies that the linear memory imported by the Wasm module is the
memoryvariable from theenvmodule.options( link: { "wasm": { "import-memory": { "module": "env", "name": "memory", }, }, "wasm-gc": { "import-memory": { "module": "env", "name": "memory", }, }, }, )
{ "link": { "wasm": { "import-memory": { "module": "env", "name": "memory" } }, "wasm-gc": { "import-memory": { "module": "env", "name": "memory" } } } }
memory-limitsオプションは、Wasm モジュールが使用する線形メモリの最小サイズと最大サイズを指定するために使います。shared-memoryオプションは、共有線形メモリを有効にするために使います。たとえば、次の設定では
wasmとwasm-gcの両バックエンドに対してメモリ制限を設定し、共有メモリを有効にしています。options( link: { "wasm": { "memory-limits": { "min": 1, "max": 65536, }, "shared-memory": true, }, "wasm-gc": { "memory-limits": { "min": 1, "max": 65535, }, "shared-memory": true, }, }, )
{ "link": { "wasm": { "memory-limits": { "min": 1, "max": 65536 }, "shared-memory": true }, "wasm-gc": { "memory-limits": { "min": 1, "max": 65535 }, "shared-memory": true } } }
The
export-memory-nameoption is used to specify the name of the linear memory exported by the Wasm module.options( link: { "wasm": { "export-memory-name": "memory", }, "wasm-gc": { "export-memory-name": "memory", }, }, )
{ "link": { "wasm": { "export-memory-name": "memory" }, "wasm-gc": { "export-memory-name": "memory" } } }
Wasm Linear Backend Link Options#
The
heap-start-addressoption is used to specify the starting address of the linear memory that can be used when compiling to the Wasm backend.For example, the following configuration sets the starting address of the linear memory to 1024.
options( link: { "wasm": { "heap-start-address": 1024, }, }, )
{ "link": { "wasm": { "heap-start-address": 1024 } } }
Wasm GC Backend Link Options#
use-js-builtin-stringオプションは、Wasm GC バックエンドへコンパイルする際に JS String Builtin Proposal を有効にするかどうかを指定します。これにより、MoonBit のStringは JavaScript ホストランタイムのStringと等価になります。For example, the following configuration enables the JS String Builtin.
options( link: { "wasm-gc": { "use-js-builtin-string": true, }, }, )
{ "link": { "wasm-gc": { "use-js-builtin-string": true } } }
The
imported-string-constantsoption is used to specify the imported string namespace used by the JS String Builtin Proposal, which is "_" by default. It should meet the configuration in the JS host runtime.For example, the following configuration and JS initialization configures the imported string namespace.
options( link: { "wasm-gc": { "use-js-builtin-string": true, "imported-string-constants": "_", }, }, )
{ "link": { "wasm-gc": { "use-js-builtin-string": true, "imported-string-constants": "_" } } }
const { instance } = await WebAssembly.instantiate(bytes, {}, { importedStringConstants: "strings" });
JS Backend Link Options#
The
exportsoption is used to specify the function names to export in the JavaScript module.For example, in the following configuration, the
hellofunction from the current package is exported as thehellofunction in the JavaScript module. In the JavaScript host, thehellofunction can be called to invoke thehellofunction from the current package.options( link: { "js": { "exports": [ "hello" ], }, }, )
{ "link": { "js": { "exports": [ "hello" ] } } }
The
formatoption is used to specify the output format of the JavaScript module.The currently supported formats are:
esm(default)cjsiife
For example, the following configuration sets the output format of the current package to ES Module.
options( link: { "js": { "format": "esm", }, }, )
{ "link": { "js": { "format": "esm" } } }
Native Backend Link Options#
The
ccoption is used to specify the compiler for compiling themoonc-generated C source files. It can be either a full path to the compiler or a simple name that is accessible via the PATH environment variable.options( link: { "native": { "cc": "/usr/bin/gcc13", }, }, )
{ "link": { "native": { "cc": "/usr/bin/gcc13" } } }
The
cc-flagsoption is used to override the default flags passed to the compiler. For example, you can use the following flag to define a macro called MOONBIT.options( link: { "native": { "cc-flags": "-DMOONBIT", }, }, )
{ "link": { "native": { "cc-flags": "-DMOONBIT" } } }
The
cc-link-flagsoption is used to override the default flags passed to the linker. Since the linker is invoked through the compiler driver (e.g.,ccinstead ofld,clinstead oflink), you should prefix specific options with-Wl,or/linkwhen passing them.The following example strips symbol information from produced binary.
options( link: { "native": { "cc-link-flags": "-s", }, }, )
{ "link": { "native": { "cc-link-flags": "-s" } } }
The
stub-ccoption is similar toccbut controls which compiler to use for compiling stubs. Although it can be different fromcc, it is not recommended and should only be used for debugging purposes. Therefore, we strongly recommend to specifyccandstub-ccat the same time and make them consistent to avoid potential conflicts.The
stub-cc-flagsis similar tocc-flags. It only have effects on stubs compilation.The
stub-cc-link-flagsare similar but have a subtle difference. Normally, stubs are compiled into object files and linked against object files generated frommoonc-generated C source files. This linking is only controlled bycc-flagsandcc-link-flags, as mentioned earlier. However, in specific modes, such as when the fast-debugging-test feature is enabled, there will be a separate linking procedure for stub objects files, wherestub-cc-link-flagswill take effect.
Default C compiler and compiler flags for the native backend#
Here is a brief summarization to compiler_flags.rs
C Compiler#
Search in PATH for the following items from top to bottom.
cl
gcc
clang
cc
the internal tcc
For GCC-like compilers, the default compile & link command is as follows.
[] is used to indicate the flags may not exist in some modes.
cc -o $target -I$MOON_HOME/include -L$MOON_HOME/lib [-g] [-shared -fPIC] \
-fwrapv -fno-strict-aliasing (-O2|-Og) [$MOON_HOME/lib/libmoonbitrun.o] \
$sources -lm $cc_flags $cc_link_flags
For MSVC, the default compile & link command is as follows.
cl (/Fo|/Fe)$target -I$MOON_HOME/include [/LD] /utf-8 /wd4819 /nologo (/O2|/Od) \
/link /LIBPATH:$MOON_HOME/lib
rule と dev_build#
rule は再利用可能なコマンドを宣言し、dev_build は具体的な入力ファイルと出力ファイルに rule を適用します。これらの事前ビルドステップは、moon check、moon build、moon test などの開発用コマンドの前に実行されます。
この仕組みは、パッケージ作者がパッケージ開発中に使用することを想定しています。そのパッケージが下流ユーザーの依存関係として使われる場合、セキュリティ上の理由から、これらの事前ビルドステップは実行されません。そのため、依存関係がビルド中に任意のコマンドを実行することはありません。生成された出力ファイルをリポジトリにコミットし、下流ユーザーがそれらを直接使ってビルドできるようにしてください。
rule(name: "...", command: "...") は再利用可能なコマンドテンプレートを宣言します。name フィールドはその rule を識別し、command はシェルコマンド文字列です。コマンドは $input と $output を参照できます。これらは、その rule を使用する dev_build エントリから提供されます。パッケージは複数の rule エントリを宣言できます。
dev_build(rule: "...", input: "...", output: "...") は事前ビルドステップを宣言します。これは rule を選択し、その rule のコマンドを展開するときに使用する入力パスと出力パスを提供します。パッケージは複数の dev_build エントリを宣言できます。
rule は、同じ moon.pkg 内のパッケージレベル rule として宣言することも、moon.mod 内のモジュールレベル rule として宣言することもできます。パッケージレベル rule は、同じ moon.pkg 内の dev_build エントリからのみ参照できます。モジュールレベル rule は、モジュール内のすべてのパッケージの dev_build エントリから参照できます。rule 名を解決するとき、moon はまず同じ moon.pkg 内のパッケージレベル rule を探し、次に moon.mod 内のモジュールレベル rule を探します。
rule(name: "copy", command: "cat $input > $output")
dev_build(rule: "copy", input: "a.txt", output: "a.mbt")
moon.pkg.json では rule エントリと dev_build エントリはサポートされていません。代わりに、非推奨の pre-build 設定を使用してください:
{
"pre-build": [
{
"input": "a.txt",
"output": "a.mbt",
"command": "cat $input > $output"
}
]
}
この例では、moon check などの開発用コマンドを実行すると、パッケージがチェックされる前に a.txt の内容が a.mbt にコピーされます。
Warnings List#
Used to disable warnings, enable warnings, or treat a warning as a fatal error. The warning list is a string composed of multiple warning name, each prefixed with a sign:
-to disable the warning+to enable the warning@to treat the enabled warning as a fatal error
For example, in the following configuration, -unused_value disables the unused functions and variables warning.
warnings = "-unused_value"
{
"warn-list": "-unused_value"
}
If multiple warnings need to be disabled, they can be directly connected and combined.
warnings = "-unused_value-unreachable_code"
{
"warn-list": "-unused_value-unreachable_code"
}
If it is necessary to activate certain warnings that were originally prohibited, use the plus sign.
warnings = "+unused_optional_argument"
{
"warn-list": "+unused_optional_argument"
}
To treat a warning as a fatal error, use the @.
warnings = "@deprecated"
{
"warn-list": "@deprecated"
}
You can also use warning numbers in warn-list. In the output below, mnemonic
is the symbolic warning name used in warning lists, while id is the numeric
form of the same warning.
The current list from moonc check -warn-help is:
Available warnings:
mnemonic description id state
unused_value Unused variable or function. 1 warn
unused_value Unused variable. 2 warn
unused_type_declaration Unused type declaration. 3 warn
missing_priv Unused abstract type. 4 warn
unused_type_variable Unused type variable. 5 warn
unused_constructor Unused constructor. 6 warn
unused_field Unused field or constructor argument. 7 warn
redundant_modifier Redundant modifier. 8 warn
struct_never_constructed Struct never constructed. 9 warn
unused_pattern Unused pattern. 10 warn
partial_match Partial pattern matching. 11 error
unreachable_code Unreachable code. 12 warn
unresolved_type_variable Unresolved type variable. 13 warn
alert or alert_<category> All alerts or alerts with specific category. 14 warn
unused_mut Unused mutability. 15 error
parser_inconsistency Parser inconsistency check. 16 warn
ambiguous_loop_argument Ambiguous usage of loop argument. 17 warn
useless_loop Useless loop expression. 18 warn
deprecated Deprecated API usage. 20 warn
missing_pattern_arguments Some arguments of constructor are omitted in pattern. 21 warn
ambiguous_block Ambiguous block. 22 warn
unused_try Useless try expression. 23 warn
unused_error_type Useless error type. 24 warn
test_unqualified_package Using implicitly imported API in test. 25 off
unused_catch_all Useless catch all. 26 warn
deprecated_syntax Deprecated syntax. 27 warn
todo Todo 28 warn
unused_package Unused package. 29 warn
missing_package_alias Empty package alias. 30 warn
unused_optional_argument Optional argument never supplied. 31 off
unused_default_value Default value of optional argument never used. 32 off
text_segment_excceed Text segment exceed the line or column limits. 33 warn
implicit_use_builtin Implicit use of definitions from `moonbitlang/core/builtin`. 34 warn
reserved_keyword Reserved keyword. 35 warn
loop_label_shadowing Loop label shadows another label. 36 warn
unused_loop_label Unused loop label. 37 warn
missing_invariant For-loop is missing an invariant. 38 off
missing_reasoning For-loop is missing a proof_reasoning. 39 off
multiline_string_escape Deprecated escape sequence in multiline string. 40 error
missing_rest_mark Missing `..` in map pattern. 41 warn
invalid_attribute Invalid attribute. 42 warn
unused_attribute Unused attribute. 43 warn
invalid_inline_wasm Invalid inline-wasm. 44 error
unused_rest_mark Useless `..` in pattern 46 warn
invalid_mbti Invalid mbti file 47 warn
missing_definition Unused pub definition because it does not exist in mbti file. 49 warn
method_shadowing Local method shadows upstream method 50 warn
ambiguous_precedence Ambiguous operator precedence 51 warn
unused_loop_variable Loop variable not updated in loop 52 warn
unused_trait_bound Unused trait bound 53 warn
ambiguous_range_direction Ambiguous looping direction for range e1..=e2 54 off
unannotated_ffi Unannotated FFI param type 55 error
missing_pattern_field Missing field in struct pattern 56 warn
missing_pattern_payload Constructor pattern expect payload 57 warn
unaligned_byte_access Unaligned byte access in bits pattern 59 warn
unused_struct_update Unused struct update 60 warn
duplicate_test Duplicate test name 61 warn
invalid_cascade Calling method with non-unit return type via `..` 62 warn
syntax_lint Syntax lint warning 63 warn
unannotated_toplevel_array Unannotated toplevel array 64 warn
prefer_readonly_array Suggest ReadOnlyArray for read-only array literal 65 off
prefer_fixed_array Suggest FixedArray for mutated array literal 66 off
unused_async Useless `async` annotation 67 warn
declaration_unimplemented Declaration is unimplemented 68 warn
declaration_implemented Declaration is already implemented 69 off
deprecated_for_in_method using `iterator()` method for `for .. in` loop. 70 off
core_package_not_imported Packages in `moonbitlang/core` need to be explicitly imported. 71 warn
unqualified_local_using unqualified local using 72 off
unnecessary_annotation unnecessary type annotation 73 off
missing_doc Missing documentation for public definition 74 off
A all warnings
state: warn = enabled, error = promoted to error, off = disabled
note: default alert exceptions: alert_unsafe=off
注釈
Use moonc check -warn-help to see the list of preset compiler warnings.
Alert Warning#
Alerts are special warnings that indicate the usage of API marked with
#internal attribute.
All alerts has a category associated with it, which is customized by the author of the API.
You can enable or disable specific alert categories using the alert_<category> warning name,
or use alert to control all alert warnings at once.
For example, in the following configuration, all warnings for alerts are treated
as fatal errors, except for the unsafe category, which is disabled.
warnings = "@alert-alert_unsafe"
{
"warn-list": "@alert-alert_unsafe"
}
Virtual Package#
A virtual package serves as an interface of a package that can be replaced by actual implementations.
Declarations#
The virtual field is used to declare the current package as a virtual package.
For example, the following declares a virtual package with default implementation:
options(
virtual: {
"has-default": true,
},
)
{
"virtual": {
"has-default": true
}
}
Implementations#
The implement field is used to declare the virtual package to be implemented by the current package.
For example, the following implements a virtual package:
options(
implement: "moonbitlang/core/abort",
)
{
"implement": "moonbitlang/core/abort"
}
Overriding implementations#
The overrides field is used to provide the implementations that fulfills an imported virtual package.
For example, the following overrides the default implementation of the builtin abort package with another package:
options(
overrides: [ "moonbitlang/dummy_abort/abort_show_msg" ],
)
{
"overrides": ["moonbitlang/dummy_abort/abort_show_msg"]
}