Moulin User reference manual¶
Invoking moulin¶
moulin has one mandatory parameter - the file name of the build description. It should be in YAML format. You may use a regular local file or URL. moulin detects URL by the presence of a protocol prefix, like https://. If you use the URL to GitHub or another network repository, you can use the URL for the raw file only, not for a web page with that file. For example, this URL points to the correct YAML file: https://raw.githubusercontent.com/xen-troops/meta-xt-prod-devel-rcar/master/prod-devel-rcar.yaml. But the following URL can’t be used, because it points to GitHub’s web page: https://github.com/xen-troops/meta-xt-prod-devel-rcar/blob/master/prod-devel-rcar.yaml. Pay attention, that file will be downloaded only if a file with the same name doesn’t exist in the current folder. This is done to preserve possible local changes made by a user.
As a result, moulin will generate ninja.build file. You can
then invoke ninja to perform the actual build. moulin adds
generator rule in ninja.build, so it is not mandatory to
invoke moulin after you make changes to your YAML file. Ninja
will detect any changes to this file and invoke moulin automatically
to re-create ninja.build.
If the YAML file contains parameters key, it is possible to invoke
moulin with additional command line options. The set of these options
depends on the contents of the YAML file and can be viewed using
--help-config command line option.
Verbose output¶
Use -v or --verbose command line option to increase
the verbosity of the output. With this option enabled, moulin will give more
information about what it is doing.
Dumping intermediate state¶
--dump command line option can be used to force moulin to
dump the intermediate state of the processed YAML file. You will see the contents
of your build config after applying all parameters and expanding all
variables. This can come in handy during the debugging of your build,
because you can see what exactly is passed to fetchers and builders.
Internal command line options¶
There is --fetcherdep command line option which is internal,
and it is even hidden from -h output. It is used by moulin to
generate dynamic dependency files for Ninja, so Ninja can track changes
inside components.
This option is not meant to be used by a user.
YAML sections¶
The YAML file should consist of several predefined keys or sections, which are discussed below. Any unknown keys are ignored. Right now, only the following top-level keys are supported:
desc- mandatorymin_ver- optionalcomponents- mandatoryimages- optional. See rouge documentation.variables- optionalparameters- optional
Minimal Version¶
Optional min_ver section should hold the minimal required version
of moulin. This is a text string that conforms to PEP-440. For example
min_ver: "0.2". moulin will compare this with its own version
and will stop if the required version is newer.
Mandatory sections: “desc” and “components”¶
There are only two mandatory sections: desc and
components. desc should contain a text string that
describes the build. It is displayed when moulin is invoked with
--help-config command line option.
components should contain a dictionary where the key is a component
name and value is another dictionary with component settings:
components:
component1:
build-dir: "component-build-dir" # Optional
default: true # Optional
sources:
......
builder:
.....
component2:
sources:
......
builder:
.....
There are two main parts of each component description: sources and builder.
sources is optional and can contain a list of source code definitions, which
will be fetched before starting a build:
sources:
- type: git
url: "git://git.yoctoproject.org/poky"
rev: gatesgarth
- type: repo
url: https://github.com/xen-troops/android_manifest.git
rev: android-11-master
manifest: doma.xml
All supported fetchers are listed in the Fetchers section.
builder contains build configuration for a given
component. There are multiple builder types supported. They are
described in the Builders section.
Apart from two mandatory options, component description can contain the following optional keys:
build_dir- build directory name. By default, the component’s name is used.default- if set totrue- tells Ninja that this component is a default build target. This can be omitted and Ninja will choose the build target on its own rules.
Variables¶
variables section is optional. It can contain a dictionary of variable name-value pairs:
variables:
A: "a"
B: "1%{A}%{A}" # will be expanded to "1aa"
C: "2%{B}%{B}" # will be expanded to "21aa1aa"
Variables can be used anywhere in the YAML file. During internal
pre-processing all variable references in the form of
%{variable_name} will be replaced with the actual variable value.
% is a special symbol. It can be escaped by doubling it: %%.
Variables should be used to decrease the amount of hard-coded values. Good candidates that should be moved to variables are path names, branches, hardware identifiers, etc.
Parameters¶
Often, it is desired to have some options for a build. For example, one
can want to support several different HW boards or to enable
additional features. It would not be feasible to have separate YAML
for every board-feature combination. This is where parameters come to
help. All parameters should be stored in parameters section:
parameters:
parameter1:
desc: "parameter 1 description"
option1:
default: true
overrides:
...
option2:
overrides:
...
option3:
overrides:
...
parameter2:
desc: "parameter 2 description"
option1:
overrides:
...
option2:
overrides:
...
option3:
default: true
overrides:
...
Every parameter should include mandatory desc key. Parameter
can have one or more options, one of which should have
default flag enabled.
Central part of each option is the overrides section. Contents of
this section should correspond to the top-level layout of the YAML file. All
contents of this section will be overlaid on the contents of the YAML file
during the pre-processing stage. Rules of this process are:
Dictionaries are extended with new keys from
overridessection.If the dictionary already has the key:
If type of original value differs from type of
overridessection value, error is generated.If key’s value is a scalar (number, boolean, string) that it is replaced with value from
overridessection.If key’s value is an another dictionary, process start recursively.
If key’s value is a list, it is expanded with values from
overridessection.
Order of parameter application is not specified.
Basically, these rules follow the intuitive idea of extending/overwriting original config: primitive values will be overwritten, all other values will be extended.
User can choose parameter options using command line arguments, as described in the Invoking moulin section.
Fetchers¶
Fetchers are the moulin plugins responsible for downloading
sources listed in sources section of a component.
moulin will generate phony Ninja target
fetch-{component_name} for every component. It can be used to
just fetch sources without building anything.
git fetcher¶
git fetcher is used to download code from a remote or local git repository. There is a complete list of supported parameters:
type: git # Selects `git` fetcher
url: "url://for.repository/project.git"
rev: revision_name
dir: "directory/where/store/code"
depth: 1
submodules: true
type- mandatory - should begitto enable git fetcher.url- mandatory - repository URL. You can provide any URL that is supported by git itself.rev- optional - revision that should be checked out after cloning. Can be any gittree-ishlike branch name, tag, or commit ID. If this option is omitted, git will checkout the default branch.dir- optional - directory name which should be used for cloning. If this option is missed, moulin will try to guess the directory name fromurl. This path is relative to the component’s build directory.submodules- optional - boolean. Fetch submodules along with main repository.depth- optional - cloning depth. Corresponds to--depthoption forgit clone. If used together withsubmodulesenabled, it will callgitwith--shallow-submodules
repo fetcher¶
repo fetcher is used to download code using Google’s repo tool. Full list of supported options:
type: repo # Selects `repo` fetcher
url: https://manifest.address/repo.git
rev: manifest-revision
manifest: manifest-file.xml
depth: 1
groups: all
dir: "."
type- mandatory - should berepoto enable repo fetcher.url- mandatory - manifest repository URL. You can provide any URL that is supported by repo itself. This corresponds to repo’s-uoption.rev- optional - manifest revision. Corresponds to repo’s-boption.manifest- optional - manifest file name. Corresponds to repo’s-moption.depth- optional - cloning depth of internal repositories. Corresponds to repo’s--depthoption. Setting it to 1 will sufficiently decrease the fetching time.groups- optional - name of manifest groups that should be synced. Corresponds to repo’s-goption. You can use it to choose which project groups need to be synced.dir- optional - directory name which should be used for code storage. If it is missing, moulin will use"."to initialize repo repository right in the component’s build directory, as this is a main repo use case.
http fetcher¶
http fetcher is used to download a file via HTTP or HTTPS protocol. It uses
curl tool to do so. Complete list of supported options:
type: http # Selects `http` fetcher
url: "https://example.com/file.txt"
filename: "file.txt"
dir: "."
type- mandatory - should behttpto use http fetcher. Use the same type even if you are downloading over the HTTPS protocol.url- mandatory - URL of a file to be downloadedfilename- optional (in most cases) - name of the output file. If omitted, moulin will try to guess it from a URL. But if you can’t do so, it will ask you to provide the filename manually.dir- optional - directory name where to store a downloaded file. If it is omitted, moulin will use"."to download a file right into the component’s root directory.
unpack fetcher¶
unpack fetcher is used to unpack already available archives to a specified directory. An example use case is when we need to use a 3rd-party code/resources that are not available in the git repository. Complete list of supported options:
type: unpack # Selects `unpack` fetcher
archive_type: tar
file: my_file.tar.gz
dir: "."
type- mandatory - should beunpackto enable unpack fetcher.archive_type- mandatory - type or archive. Nowtarandzipare supported.file- mandatory - name of the archive filedir- optional - directory name which should be used for code storage. If it is missing, moulin will use"."to unpack the archive right into the component directory.
Currently, unpack fetcher supports two archive types: tar and zip.
taractually supports not only plain .tar archives, but also compressed archives like .tar.gz, .tar.bz2, and so on. We rely on tar ability to select the right decompressor automatically.zip- this is classic zip format.unziptool is used to decompress this kind of archive, so it should be present on the user’s machine.
west fetcher¶
west fetcher is used to download code using Zephyr’s west meta-tool. Complete list of supported options:
type: west # Selects `west` fetcher
url: https://manifest.address/zephyr
rev: manifest-revision
file: manifest-file.yml
type- mandatory - should bewestto enable west fetcher.url- optional - manifest repository URL. You can provide any URL that is supported by west itself. This corresponds to west init’s-moption.rev- optional - manifest revision. Corresponds to west init’s--mroption.file- optional - manifest file name. Corresponds to west init’s--mfoption.
For additional details, see documentation on west init: https://docs.zephyrproject.org/latest/develop/west/built-in.html#west-init
Regarding installation of west, please see: https://docs.zephyrproject.org/latest/develop/west/install.html
null fetcher¶
null fetcher does nothing. It can be used for testing or in some tricky situation when you want to have a component without fetchers.
type: "null" # Selects `none` fetcher
type- mandatory - should be"null"to use null fetcher. Please note that you need to use quotes; otherwise, the YAML parser will treat it as a null type.
Builders¶
Builders are the moulin plugins responsible for actual image building.
moulin will generate phony Ninja target
{component_name} for every component. It can be used to
build a certain component. Please note that this will not build only
given component. Any prerequisites will be fetched and built as well.
Builder configuration heavily depends on the builder type and is described in the next subsections.
yocto builder¶
Yocto builder is used to build OpenEmbedded-based images. It expects
that poky repository is cloned in {build_dir}/poky and uses
it’s poky/oe-init-build-env script to initialize build
environment. Then bitbake-layers tool is used to add
additional layers and bitbake used to perform the build.
builder:
type: yocto # Should be `yocto`
base_distro: poky # Optional
work_dir: "build" # Optional
build_target: core-image-minimal # Mandatory
conf: # Mandatory
- [MACHINE, "machine-name"]
- [DISTRO_FEATURES_remove, "feature_to_remove"]
- [DISTRO_FEATURES_append, "feature_to_add"]
layers: # Optional
- "../poky/meta-yocto-bsp"
- "../meta-other-layer/"
external_src: # Optional
"package-name": "path-to-package-sources"
"another-package-name": ["path part1", "path part2", "path part3"]
target_images: # Mandatory
- "tmp/deploy/images/machine-name/Image"
additional_deps: # Optional
- "path/to/file/generated/by/other/component"
Mandatory options:
type- Builder type. Should beyoctofor this type of builder.build_target- bitbake’s build target. This will be used to run the build:$ bitbake {build_target}target_images- list of image files that should be generated by this component as a result of invoking$ bitbake {build_target}. Every component should generate at least one image file.
Optional parameters. Those provide advanced features that may be needed if you are building multiple VMs with cross-dependencies.
base_distro- provides name of base distro directory. Default value ispokyfor compatibility reasons. For newer Yocto releases you want to useopenembedded-core. Currently this only affects location ofoe-init-build-envscript.conf- list of additionallocal.confoptions. Please note that each entry inconflist is not akey:valuepair, but another list of two items. We use this format because it is possible to have multiplelocal.confentries with the same key. Those entries will not be written straight intolocal.conf. Instead, a new filemoulin.confwill be created. This file will then be included fromlocal.conf.layers- list of additional layers. Those layers will be added to the build usingbitbake-layers add-layer {layers}command.work_dir- bitbake’s work directory. The default value is “build”. This is where files like “conf/local.conf” are stored. You can overwrite so you can produce multiple builds from the same (or different) set of Yocto layers.additional_deps- list of additional dependencies. This is basicallytarget_imagesproduced by other components. You can use those to implement build dependencies between components. For example, if your system needs to have DomU’s kernel image on Dom0’s file system, you might want to add the path to DomU’s kernel intoadditional_depsof Dom0’s config. This will ensure that Dom0 will be built after DomU.external_src- list of external sources for packages. This option will make moulin generateEXTERNALSRC:pn-{package}in local.conf. This feature is used to provide the Yocto build with artifacts that were built outside of the tree. Such artifacts can be provided by another component, for example.
bazel builder¶
Bazel builder is used to build projects based on the Bazel build system provided by Google. It expects that a project with source and Bazel configuration files is present in the build directory.
builder:
type: "bazel" # Mandatory and must be `bazel`
tool: "tools/bazel" # Optional
startup-options: # Optional
- "--max_idle_secs=1"
command: run # Optional
args: # Optional
- "--verbose_failures"
- "--sandbox_debug"
target: # Mandatory
target-patterns: # Optional
- "--dist_dir=path_to_dist"
target_images: # Mandatory
- "out/deploy/virtual-device/virtual_device_aarch64/Image"
- "out/deploy/virtual-device/virtual_device_aarch64/initramfs.img"
Mandatory parameters:
type- Builder type. It must bebazelfor this type of builder.target- target name that should be described in the corresponding BUILD.bazel file and must satisfy bazel rules.target_images- list of artifact files that should be generated by this component as a result of the build. Every component should generate at least one image file.
Optional parameters:
tool- the relative path to the Bazel tool in relation to the ‘build-dir’. If this parameter is not defined, the system-installed Bazel tool will be used.startup-options- Bazel startup options that appear before the command and are parsed by the client.command- bazel command. By default,buildis used.args- bazel arguments related to the concretecommand.target-patterns- bazel target patterns to be built or parameters to the executable target.
android builder¶
Android builder is used to build the Android Open Source Project (AOSP). It expects that AOSP is present in the build directory. In most cases, AOSP is cloned using the repo fetcher.
builder:
type: android # Should be 'android'
env: # Optional
- "TARGET_BOARD_PLATFORM=r8a7795"
lunch_target: xenvm-userdebug
target_images:
- "out/xenvm/userdebug/boot.img"
- "out/xenvm/userdebug/system.img"
additional_deps: # Optional
- "path/to/file/generated/by/other/component"
Mandatory options:
type- Builder type. Should beandroidfor this type of builder.lunch_target- lunch’s build target. This will be used to run the build:$ lunch {lunch-target}target_images- list of image files that should be generated by this component as a result of invoking$ m. Every component should generate at least one image file.
Optional parameters:
env- list of additional environment variables that should be exported before callinglunch.
android_kernel builder¶
Android Kernel builder is used to build the kernel and kernel modules for Android Open Source Project (AOSP). It expects that the correct directory layout is present in the build directory. In most cases, AOSP is cloned using the repo fetcher.
builder:
type: android_kernel # Should be 'android_kernel'
env: # Optional
- "TARGET_BOARD_PLATFORM=r8a7795"
- "BUILD_CONFIG=common/build.config.xenvm"
- "SKIP_MRPROPER=1"
target_images:
- "out/android12-5.4/common/arch/arm64/boot/Image"
Mandatory options:
type- Builder type. Should beandroid_kernelfor this type of builder.target_images- list of image files that this component should generate as a result of invokingbuild.shscript. Every component should generate at least one image file.
Optional parameters:
env- list of additional environment variables that should be exported before callingbuild.sh.additional_deps- list of additional dependencies. This is basicallytarget_imagesproduced by other components. You can use those to implement build dependencies between components. For example, if your Android build needs a Linux kernel built by some other component, you might want to add path to linux kernel image provided by this component intoadditional_deps. This will ensure that Linux kernel will be built before Android.
archive builder¶
Archive builder is intended to create an archive from other components. It can be used to gather build artifacts, for example. This builder uses tar to create archive files. Archives can be optionally compressed as, tar is invoked with –auto-compress option.
builder:
type: archive # Should be 'archive'
name: "artifacts.tar.bz2"
base_dir: "yocto/build/tmp/deploy/images/"
items:
# items are relative to base_dir
- "generic-armv8-xt/Image"
- "generic-armv8-xt/uInitramfs"
Mandatory options:
type- Builder type. It should bearchivefor this type of builder.name- Name of an archive file. Add a suffix like tar.bz2 to make tar compress archive with desired compressing algorithm.base_dir- Optional parameter specifying tar’s base directory. The default value is “.” if not specified. This is passed to tar as -C option. As result, the final archive will contain paths relative tobase_dir. Avoid using .. because specified items will be archived by tar but all .. will be stripped. As a result, the archive will contain items with unexpected paths.items- list of files or directories that should be added to the archive. Please ensure that those files or directories are present in other componentstarget_imagessections, so Ninja can build correct dependencies. All paths are relative to thebase_dir.
zephyr builder¶
This builder is used to build applications based on Zephyr OS. It uses Zephyr OS meta-tool west. Required code is expected to be fetched by west fetcher.
builder:
type: zephyr
board: xenvm
shields: # Optional
- "shield1"
- "shield2"
target: samples/synchronization
work_dir: build_dir
target_images:
- "zephyr/build/zephyr/zephyr.bin"
vars:
- "VAR1=var1_value"
env:
- "MY_ENV_VAR=my_value"
additional_deps: # Optional
- "path/to/file/generated/by/other/component"
Mandatory options:
type- builder type. Should bezephyrfor this type of builder.board- target board name. For example: xenvm or xenvm_gicv3 for Xen-based builds. Corresponds to west build’s-boption. See Zephyr’s documentation for the list of allowed values.target- build target. This will be used to run the build:$ west build {target}. For example: samples/synchronization or samples/hello_world.target_images- list of image files that this builder should generate. For the standard build, it is expected to be “zephyr/build/zephyr/zephyr.bin”
Optional parameters:
env- list of additional environment variables that should be exported before callingwest build.work_dir- build system’s work directory. Default value is “build”. This is where files produced by the build system are stored.additional_deps- list of additional dependencies. This is basicallytarget_imagesproduced by other components. You can use those to implement build dependencies between components. For example, if your system needs to have DomU’s kernel image in your zephyr image, you might want to add the path to DomU’s kernel intoadditional_depsof zephyr’s config. This will ensure that zephyr will be built after DomU.shields- list of shields should be integrated to zephyr board(For Zephyr < 3.4.0).snippets- list of snippets should be integrated to zephyr board(For Zephyr >= 3.4.0). Please note that only one ofshieldsandsnippetscan be used at the same time.vars- list of additional variables that should be passed to CMake viawest build.
Please note that this builder uses --pristine=auto command-line option.
Proper versions of CMake and the Zephyr SDK must be installed on the host.
For additional details, please see https://docs.zephyrproject.org/latest/develop/west/build-flash-debug.html#building-west-build
custom_script builder¶
The custom-script builder is designed to perform custom actions. This builder
actually calls the script pointed in option script. Builder node
is stored in the file in work_dir directory, and that file is passed to the
script as parameter
builder:
type: custom_script # Should be 'custom_script'
work_dir : "script_workdir"
script: "path/to/script/custom_script.py"
args:
- "argument1"
- "argument2"
config:
items:
"rootfs": "images/spider/rootfs.tar.bz2"
manifest:
"id": ""
"vendorVersion": "0.2.0"
"fileName": "archive.squashfs"
"description": "DomD image"
"bundleType": "full"
target_images:
- "custom_script_targets"
additional_deps: # Optional
- "path/to/file_name"
Mandatory options:
type- Builder type. It should becustom_scriptfor this type of builder.work_dir- build script work directory. Default value is “script_workdir”. This is where files produced by the build system are stored.script- path to script which performs custom actions. Whole yaml node will be stored to a file, and the name of that file will be passed toscriptas the last command line argument.target_images- list of files that should be generated by script.
Optional parameters:
args- additional arguments should be passed toscript. Can be passed as a string or a listadditional_deps- list of additional dependencies. This is basicallytarget_imagesproduced by other components. You can use those to implement build dependencies between components. For example, if your system needs to have DomU’s kernel image for your fota archive, you might want to add the path to DomU’s kernel intoadditional_depsof Dom0’s config. This will ensure that the FOTA archive will be built after DomU.Remaining parameters should be parsed and used by the script pointed in
scriptoption.
null builder¶
“null” builder does nothing at all. It does not even generate dependencies. It can be used for testing or in cases when you need to call the fetcher only. Please note that Ninja will not call fetcher for the component if fetcher’s output file is not used by anything.
builder:
type: "null" # Should be "null"
Mandatory options:
type- Builder type. It should be"null"for this type of builder. Please note that you need to use quotes; otherwise, the YAML parser will treat it as a null type.