5.5 KiB
Script Modules
With muon, you can write modules in an extended form of the meson dsl. This is for a number of reasons:
- Many meson modules are effectively reusable chunks of meson code (calls to dependency, custom_target, etc.), so it is not necessary to access things that a native module has access to like the interpreter state.
- Lowering the bar for module contributions (this is important because they often involve specific tools I have no experience with/interest in).
- Potential to some day share module code with other meson implementations.
That last point is a bit pie in the sky, but at least this makes it technically possible from muon's point of view and proves that it has value.
Writing a new script module
All script modules live at src/script/modules/<module_name>.meson. After
adding a new module, you must modify src/script/meson.build to register it.
muon will embed the module source text as a char[] in the built executable, and
when the module is import()ed that source will be interpreted.
Module structure
A script module consists of functions that perform the various module operations, with a return statement at the bottom of the file that exports those functions.
func func1()
endfunc
func func2()
endfunc
return {
'func1': func1,
'func2': func2,
}
The final return at module scope is what "exports" the functions to module
consumers. The returned object must be of type dict[func].
Functions
Function definition is started with the func keyword followed by an
identifier, and a list of arguments enclosed in parenthesis. If the function
returns a value it must specify the type of that value by adding -> <type>
after the argument list.
Positional and keyword arguments are supported in the argument list. Positional arguments must come first. Keyword arguments are specified by adding a colon (:) to the end of the argument followed by an optional default value. All arguments must also specify their type by following the argument name with a type specifier.
Examples:
func a() -> int
return 1
endfunc
func b(arg1 int) -> int
return arg1
endfunc
func b(arg1 int, kw str:, kw_with_default str: 'default')
message(arg1)
message(kw)
message(kw_with_default)
endfunc
Scope
Scope generally works like other interpreted languages.
Modules have their own scope and cannot access any external variables (save builtins such as meson, build_machine, etc.).
Functions also get their own scope, but can see variables that have been declared in parent scopes prior to the function definition. Function definitions also capture their scope.
Example:
func a() -> func
i = 0
func b() -> int
i += 1
return i
endfunc
return b
endfunc
counter = a()
counter() #=> 1
counter() #=> 2
new_counter = a()
new_counter() #=> 1
new_counter() #=> 2
counter() #=> 3
Type specifiers
Type specifiers take the form of the ones found in the meson docs. The following types are allowed:
voidcompilerdepmesonstrintlistdictboolfilebuild_tgtsubprojectbuild_machinefeatureexternal_programpython_installationrunresultcfg_datacustom_tgttestmoduleinstall_tgtenvincoptiondisablergeneratorgenerated_listalias_tgtboth_libstypeinfofuncsource_setsource_configuration
In addition, a value that can take one of many types can be specified by writing
multiple types separated with a |.
int|str
dict|list|str
There are a few preset combinations of types:
any- all of the above types exceptvoidexe-str|file|external_program|python_installation|build_tgt|custom_tgt
dict and list should also be followed by a sub-type enclosed in square
brackets.
dict[str]
dict[str|int]
Finally, you can wrap the entire type in glob[<type>] or listify[<type>] to
get the special argument handling detailed in doc/contributing.md (search for
TYPE_TAG_{GLOB,LISTIFY}.
Additional built-in functions
Various additional builtin functions are avaliable:
serial_load(path str) -> any- load a serialized object from a fileserial_dump(path str, obj any)- serialize and save an object to a fileis_void(arg any) -> bool- check if arg is the value void. This can be used to check if a kwarg with no default value has been set.typeof(arg any) -> str- returns the type of an object.list.delete(index int)- delete the element from list at the specefied indexdict.delete(key str)- delete key from dict
The fs module also has additonal functions:
copy(src str|file, dest str)- copy a file from src to destwrite(dest str|file, data str)- writedatatodestcwd() -> str- returns muon's current working directorymkdir(path str)- make the directory atpathis_basename(path str) -> bool- true if str contains no path separatorsis_subpath(base str, sub str) -> bool- true ifsubis a subpath ofbaseadd_suffix(path str, suff str) -> str- add the suffixsufftopathmake_absolute(path str) -> str- prepend cwd topathif path is relativerelative_to(base str, sub str) -> str- return pathsubrelative tobasewithout_ext(path str) -> str- return path with extension removed to it, otherwise return pathexecutable(path str) -> str- if path has no path separators, prepend './'