Picking ports to install using ports.yaml

To include a specific port in a Phoenix-RTOS build, the appropriate ports.yaml file for the given target must be modified.

A ports.yaml is a YAML file that defines which ports are included in a build and how they are configured. It may also use Jinja2 templating, allowing build-time configuration based on environment variables.

Static example of ports.yaml

The following ports.yaml requests a simple (unconditional) installation of busybox and a complex installation of a lua port:

tests: true                     # Optional. Default: false
ports:
  - name: busybox               # Required. String. Must match port.def.sh 'name' of port
  - name: lua                   
    tests: true                 # Optional. Boolean. Default: false. AND-ed with global 'tests'
    use: ["safe"]               # Optional. List of strings. Default: []
  - heatshrink                  # Shorthand notation for `name: heatshrink`

The global tests field controls the test building for all ports that specify per-port tests field by AND-ing the fields. Thus, in the above case, despite the global tests: true the busybox will be built without tests, as it doesn’t specify the per-port tests field, and it defaults to false. However, the lua port will be built with tests since both global and per-port fields are true.

The lua port is additionally specified to be built with a safe flag. This flag must be present in the lua port.def.sh iuse field (see: Variant flags).

Environment-dependent ports.yaml

The previous example can be rewritten so that it is controlled by the environment variables using Jinja2 snippets. In the following ports.yaml, building tests is enabled for all testable ports only if LONG_TEST=y, and the lua port is installed only if INSTALL_LUA=y:

tests: {{ bool(env.LONG_TEST) }}
ports:
  - name: busybox
  - name: lua                   
    tests: true
    use: ["safe"]
    if: {{ bool(env.INSTALL_LUA) }} # Optional. Boolean. Default: true

The bool function is a global function that can be used to convert any bool-like environment variable values (1, 0, y, n, etc.) into a proper Python boolean value. It returns false, when the environment variable is undefined.

The if field is an additional, optional attribute that controls whether a port is built. If the expression evaluates to false, the port is skipped.

Here is another ports.yaml example that uses Jinja2 if block for azure_sdk port and a conditional inclusion of variant flag longtest flag for micropython:

tests: {{ bool(env.LONG_TEST) }}
ports:
  - name: azure_sdk
    {% if bool(env.LONG_TEST) %}
    use: [longtest]
    tests: true
    {% endif %}
  - name: micropython
    use: {{ ["longtest"] if bool(env.LONG_TEST) }}
    tests: True

This example exploits the fact that the ports.yaml is first treated as a Jinja2 template, while the previous example passed Jinja2 snippets as strings.

Convenience features

Disabling multiple ports

When multiple ports.yaml files are loaded, one way to disable ports inherited from previous ports.yaml is to write if: false for each unwanted port. This quickly becomes inconvenient when there are lots of ports to disable.

The disabled-ports field allows to specify many port names to disable at once. For example, assuming bar and baz were specified in previous ports.yaml, the following ports.yaml will disable their build:

ports:
- name: foo
disabled-ports:
- bar
- baz