BuildElement - Abstract class for build elements

The BuildElement class is a convenience element one can derive from for implementing the most common case of element.

Built-in functionality

The BuildElement base class provides built in functionality that could be overridden by the individual plugins.

This section will give a brief summary of how some of the common features work, some of them or the variables they use will be further detailed in the following sections.

The strip-binaries variable

The strip-binaries variable is by default empty. You need to use the appropiate commands depending of the system you are building. If you are targetting Linux, ones known to work are the ones used by the freedesktop-sdk, you can take a look to them in their project.conf

Location for staging dependencies

The BuildElement supports the “location” dependency configuration, which means you can use this configuration for any BuildElement class.

The “location” configuration defines where the dependency will be staged in the build sandbox.

Example:

Here is an example of how one might stage some dependencies into an alternative location while staging some elements in the sandbox root.

# Stage these build dependencies in /opt
#
build-depends:
- baseproject.bst:opt-dependencies.bst
  config:
    location: /opt

# Stage these tools in "/" and require them as
# runtime dependencies.
depends:
- baseproject.bst:base-tools.bst

Note

The order of dependencies specified is not significant.

The staging locations will be sorted so that elements are staged in parent directories before subdirectories.

Location for running commands

The command-subdir variable sets where the build commands will be executed, if the directory does not exist it will be created, it is defined relative to the buildroot.

Location for configuring the project

The conf-root is defined by default as . and is the location that specific build element can use to look for build configuration files. This is used by elements such as autotools, cmake, distutils, meson, pip and qmake.

The configuration commands are run in command-subdir and by default conf-root is . so if conf-root is not set the configuration files in command-subdir will be used.

By setting conf-root to "%{build-root}/Source/conf_location" and your source elements directory variable to Source then the configuration files in the directory conf_location with in your Source will be used. The current working directory when your configuration command is run will still be wherever you set your command-subdir to be, regardless of where the configure scripts are set with conf-root.

Install Location

You should not change the install-root variable as it is a special writeable location in the sandbox but it is useful when writing custom install instructions as it may need to be supplied as the DESTDIR, please see the cmake build element for example.

Abstract method implementations

Element.configure_sandbox()

In Element.configure_sandbox(), the BuildElement will ensure that the sandbox locations described by the %{build-root} and %{install-root} variables are marked and will be mounted read-write for the assemble phase.

The working directory for the sandbox will be configured to be the %{build-root}, unless the %{command-subdir} variable is specified for the element in question, in which case the working directory will be configured as %{build-root}/%{command-subdir}.

Element.stage()

In Element.stage(), the BuildElement will do the following operations:

  • Stage all of the build dependencies into the sandbox root.

  • Run the integration commands for all staged dependencies using Element.integrate()

  • Stage any Source on the given element to the %{build-root} location inside the sandbox, using Element.stage_sources()

Element.prepare()

In Element.prepare(), the BuildElement will run configure-commands, which are used to run one-off preparations that should not be repeated for a single build directory.

Element.assemble()

In Element.assemble(), the BuildElement will proceed to run sandboxed commands which are expected to be found in the element configuration.

Commands are run in the following order:

  • build-commands: Commands to build the element

  • install-commands: Commands to install the results into %{install-root}

  • strip-commands: Commands to strip debugging symbols installed binaries

The result of the build is expected to end up in %{install-root}, and as such; Element.assemble() method will return the %{install-root} for artifact collection purposes.

class BuildElement(context: Context, project: Project, load_element: LoadElement, plugin_conf: Dict[str, Any])

Bases: buildstream.element.Element

configure(node)

Configure the Plugin from loaded configuration data

Parameters

node – The loaded configuration dictionary

Raises

Plugin implementors should implement this method to read configuration data and store it.

The MappingNode.validate_keys() method should be used to ensure that the user has not specified keys in node which are unsupported by the plugin.

configure_dependencies(dependencies)

Configure the Element with regards to it’s build dependencies

Elements can use this method to parse custom configuration which define their relationship to their build dependencies.

If this method is implemented, then it will be called with all direct build dependencies specified in their element declaration in a list.

If the dependency was declared with custom configuration, it will be provided along with the dependency element, otherwise None will be passed with dependencies which do not have any additional configuration.

If the user has specified the same build dependency multiple times with differing configurations, then those build dependencies will be provided multiple times in the dependencies list.

Parameters

dependencies (list) – A list of DependencyConfiguration objects

Raises

ElementError – When the element raises an error

The format of the MappingNode provided as DependencyConfiguration.config method should be called by the implementing plugin in order to validate it.

Note

It is unnecessary to implement this method if the plugin does not support any custom dependency configuration.

preflight()

Preflight Check

Raises

This method is run after Plugin.configure() and after the pipeline is fully constructed.

Implementors should simply raise SourceError or ElementError with an informative message in the case that the host environment is unsuitable for operation.

Plugins which require host tools (only sources usually) should obtain them with utils.get_host_tool() which will raise an error automatically informing the user that a host tool is needed.

get_unique_key()

Return something which uniquely identifies the plugin input

Returns

A string, list or dictionary which uniquely identifies the input

This is used to construct unique cache keys for elements and sources, sources should return something which uniquely identifies the payload, such as an sha256 sum of a tarball content.

Elements and Sources should implement this by collecting any configurations which could possibly affect the output and return a dictionary of these settings.

For Sources, this is guaranteed to only be called if Source.is_resolved() has returned True which is to say that the Source is expected to have an exact ref indicating exactly what source is going to be staged.

configure_sandbox(sandbox)

Configures the the sandbox for execution

Parameters

sandbox – The build sandbox

:raises (ElementError): When the element raises an error

Elements must implement this method to configure the sandbox object for execution.

stage(sandbox)

Stage inputs into the sandbox directories

Parameters

sandbox – The build sandbox

:raises (ElementError): When the element raises an error

Elements must implement this method to populate the sandbox directory with data. This is done either by staging Source objects, by staging the artifacts of the elements this element depends on, or both.

assemble(sandbox)

Assemble the output artifact

Parameters

sandbox – The build sandbox

Returns

An absolute path within the sandbox to collect the artifact from

:raises (ElementError): When the element raises an error

Elements must implement this method to create an output artifact from its sources and dependencies.

prepare(sandbox)

Run one-off preparation commands.

This is run before assemble(), but is guaranteed to run only the first time if we build incrementally - this makes it possible to run configure-like commands without causing the entire element to rebuild.

Parameters

sandbox – The build sandbox

:raises (ElementError): When the element raises an error

By default, this method does nothing, but may be overriden to allow configure-like commands.

generate_script()

Generate a build (sh) script to build this element

Returns

A string containing the shell commands required to build the element

BuildStream guarantees the following environment when the generated script is run:

  • All element variables have been exported.

  • The cwd is self.get_variable(‘build-root’)/self.normal_name.

  • $PREFIX is set to self.get_variable(‘install-root’).

  • The directory indicated by $PREFIX is an empty directory.

Files are expected to be installed to $PREFIX.

If the script fails, it is expected to return with an exit code != 0.