Commit a25d683e authored by Tristan Van Berkom's avatar Tristan Van Berkom

doc: Adding part 4 of the getting started tutorial: integration commands

This new section talks about how integration commands work
and shows them at work.
parent 1d84bb80
Pipeline #24482039 passed with stages
in 31 minutes and 30 seconds
kind: stack
description: Base stack
depends:
- base/alpine.bst
kind: import
description: |
Alpine Linux base runtime
sources:
- kind: tar
url: alpine:integration-tests-base.v1.x86_64.tar.xz
ref: 3eb559250ba82b64a68d86d0636a6b127aa5f6d25d3601a79f79214dc9703639
#
# Run ldconfig in the libdir before running anything
#
public:
bst:
integration-commands:
- ldconfig "%{libdir}"
kind: manual
description: |
The hello application
# Depend on the hello library
depends:
- libhello.bst
# Stage the files/hello directory for building
sources:
- kind: local
path: files/hello
# Now configure the commands to run
config:
build-commands:
- make PREFIX="%{prefix}"
install-commands:
- make -j1 PREFIX="%{prefix}" DESTDIR="%{install-root}" install
kind: manual
description: |
The libhello library
# Depend on the base system
depends:
- base.bst
# Stage the files/libhello directory for building
sources:
- kind: local
path: files/libhello
# Now configure the commands to run
config:
build-commands:
- make PREFIX="%{prefix}"
install-commands:
- make -j1 PREFIX="%{prefix}" DESTDIR="%{install-root}" install
# Sample makefile for hello.c
#
.PHONY: all install
all: hello
install:
install -d ${DESTDIR}${PREFIX}/bin
install -m 755 hello ${DESTDIR}${PREFIX}/bin
hello: hello.c
$(CC) $< -o $@ -Wall -lhello
/*
* hello.c - Simple hello program
*/
#include <stdio.h>
#include <libhello.h>
int main(int argc, char *argv[])
{
const char *person = NULL;
if (argc > 1)
person = argv[1];
if (person)
hello(person);
else
hello("stranger");
return 0;
}
# Sample makefile for hello library
#
.PHONY: all install
all: libhello.so
install:
install -d ${DESTDIR}${PREFIX}/lib
install -d ${DESTDIR}${PREFIX}/include
install -m 644 libhello.so ${DESTDIR}${PREFIX}/lib
install -m 644 libhello.h ${DESTDIR}${PREFIX}/include
%.o: %.c %.h
$(CC) -c $< -o $@ -Wall
libhello.so: libhello.o
$(CC) -shared -o $@ $<
/*
* libhello.c - The hello library
*/
#include <stdio.h>
void hello(const char *person)
{
printf("Hello %s\n", person);
}
/*
* libhello.h - The hello library
*/
/*
* A function to say hello to @person
*/
void hello(const char *person);
# Unique project name
name: integration-commands
# Required BuildStream format version
format-version: 9
# Subdirectory where elements are stored
element-path: elements
# Define an alias for our alpine tarball
aliases:
alpine: https://gnome7.codethink.co.uk/tarballs/
commands:
# Make it fetch first
- directory: ../examples/integration-commands
command: fetch hello.bst
# Capture a build output
- directory: ../examples/integration-commands
output: ../source/sessions/integration-commands-build.html
command: build hello.bst
# Capture a shell output
- directory: ../examples/integration-commands
output: ../source/sessions/integration-commands-shell.html
command: shell hello.bst -- hello pony
.. _public_builtin:
Builtin public data
===================
Elements can provide public data which can be read by other elements
......
This diff is collapsed.
<!--
WARNING: This file was generated with bst2html.py
-->
<div class="highlight" style="font-size:x-small"><pre>
<span style="color:#C4A000;font-weight:bold">user@host</span>:<span style="color:#3456A4;font-weight:bold">~/integration-commands</span>$ bst shell hello.bst -- hello pony
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#3465A4"><span style=""><span style="opacity:0.5">START </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Loading pipeline
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#4E9A06"><span style=""><span style="opacity:0.5">SUCCESS</span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Loading pipeline
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#3465A4"><span style=""><span style="opacity:0.5">START </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Resolving pipeline
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#4E9A06"><span style=""><span style="opacity:0.5">SUCCESS</span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Resolving pipeline
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#3465A4"><span style=""><span style="opacity:0.5">START </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Resolving cached state
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#4E9A06"><span style=""><span style="opacity:0.5">SUCCESS</span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Resolving cached state
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#3465A4"><span style=""><span style="opacity:0.5">START </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Staging dependencies
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#4E9A06"><span style=""><span style="opacity:0.5">SUCCESS</span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Staging dependencies
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#3465A4"><span style=""><span style="opacity:0.5">START </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Integrating sandbox
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#C4A000">f3a052f5</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#C4A000"> main</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">base/alpine.bst </span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#06989A"><span style=""><span style="opacity:0.5">STATUS </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Running integration command
<span style="opacity:0.5"> ldconfig "/usr/lib"</span>
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">00</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#4E9A06"><span style=""><span style="opacity:0.5">SUCCESS</span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Integrating sandbox
<span style="color:#06989A"><span style="opacity:0.5">[</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">--</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#C4A000">18c81214</span><span style="color:#06989A"><span style="opacity:0.5">][</span></span><span style="color:#C4A000"> main</span><span style="color:#06989A"><span style="opacity:0.5">:</span></span><span style="color:#C4A000">hello.bst </span><span style="color:#06989A"><span style="opacity:0.5">] </span></span><span style="color:#06989A"><span style=""><span style="opacity:0.5">STATUS </span></span></span><span style="color:#06989A"><span style="opacity:0.5"> </span></span>Running command
<span style="opacity:0.5"> hello pony</span>
Hello pony
</pre></div>
Integration commands
====================
Sometimes a software requires more configuration or processing than what is
performed at installation time, otherwise it will not run properly.
This is especially true in cases where a daemon or library interoperates
with third party extensions and needs to maintain a system wide cache whenever
it's extensions are installed or removed; system wide font caches are an example
of this.
In these cases we use :ref:`integration commands <public_integration>` to
ensure that a runtime is ready to run after all of it's components have been *staged*.
.. note::
This example is distributed with BuildStream
in the `doc/examples/integration-commands
<https://gitlab.com/BuildStream/buildstream/tree/master/doc/examples/integration-commands>`_
subdirectory.
Overview
--------
In this chapter, we'll be exploring :ref:`integration commands <public_integration>`,
which will be our first look at :ref:`public data <format_public>`.
Project structure
-----------------
``project.conf`` and ``elements/base.bst``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The project.conf and base stack :mod:`stack <elements.stack>` element are configured in the
same way as in the previous chapter: :ref:`tutorial_running_commands`.
``elements/base/alpine.bst``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. literalinclude:: ../../examples/integration-commands/elements/base/alpine.bst
:language: yaml
This is the same ``base/alpine.bst`` we've seen in previous chapters,
except that we've added an :ref:`integration command <public_integration>`.
This informs BuildStream that whenever the output of this element is
expected to *run*, this command should be run first. In this case we
are simply running ``ldconfig`` as a precautionary measure, to ensure
that the runtime linker is ready to find any shared libraries we may
have added to ``%{libdir}``.
Looking at public data
''''''''''''''''''''''
The :ref:`integration commands <public_integration>` used here is the first time
we've used any :ref:`builtin public data <public_builtin>`.
Public data is a free form portion of an element's configuration and
is not necessarily understood by the element on which it is declared, public
data is intended to be read by it's reverse dependency elements.
This allows annotations on some elements to inform elements later in
the dependency chain about details of it's artifact, or to suggest how
it should be processed.
``elements/libhello.bst`` and ``elements/hello.bst``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These are basically manual elements very similar to the ones we've
seen in the previous chapter: :ref:`tutorial_running_commands`.
These produce a library and a hello program which uses the library,
we will consider these irrelevant to the topic and leave examination
of `their sources
<https://gitlab.com/BuildStream/buildstream/tree/master/doc/examples/integration-commands/files>`_
as an exercise for the reader.
Using the project
-----------------
Build the hello.bst element
~~~~~~~~~~~~~~~~~~~~~~~~~~~
To build the project, run :ref:`bst build <invoking_build>` in the
following way:
.. raw:: html
:file: ../sessions/integration-commands-build.html
Observe in the build process above, the integration command declared on the
``base/alpine.bst`` element is run after staging the dependency artifacts
into the build sandbox and before running any of the build commands, for
both of the ``libhello.bst`` and ``hello.bst`` elements.
BuildStream assumes that commands which are to be run in the build sandbox
need to be run in an *integrated* sandbox.
.. tip::
Integration commands can be taxing on your overall build process,
because they need to run at the beginning of every build which
:ref:`runtime depends <format_dependencies_types>` on the element
declaring them.
For this reason, it is better to leave out more onerous tasks
if they are not needed at software build time, and handle those
specific tasks differently later in the pipeline, before deployment.
Run the hello world program
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Unlike the previous chapters, this hello world program takes an argument,
we can invoke the program using :ref:`bst shell <invoking_shell>`:
.. raw:: html
:file: ../sessions/integration-commands-shell.html
Here we see again, the integration commands are also used when preparing
the shell to launch a command.
Summary
-------
In this chapter we've observed how :ref:`integration commands <public_integration>`
work, and we now know about :ref:`public data <format_public>`, which plugins
can read from their dependencies in order to influence their build process.
......@@ -12,3 +12,4 @@ projects.
tutorial/first-project
tutorial/running-commands
tutorial/autotools
tutorial/integration-commands
import os
import pytest
from tests.testutils import cli_integration as cli
from tests.testutils.integration import assert_contains
from tests.testutils.site import IS_LINUX
pytestmark = pytest.mark.integration
DATA_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)), '..', '..', 'doc', 'examples', 'integration-commands'
)
@pytest.mark.skipif(not IS_LINUX, reason='Only available on linux')
@pytest.mark.datafiles(DATA_DIR)
def test_integration_commands_build(cli, tmpdir, datafiles):
project = os.path.join(datafiles.dirname, datafiles.basename)
checkout = os.path.join(cli.directory, 'checkout')
result = cli.run(project=project, args=['build', 'hello.bst'])
assert result.exit_code == 0
# Test running the executable
@pytest.mark.skipif(not IS_LINUX, reason='Only available on linux')
@pytest.mark.datafiles(DATA_DIR)
def test_integration_commands_run(cli, tmpdir, datafiles):
project = os.path.join(datafiles.dirname, datafiles.basename)
result = cli.run(project=project, args=['build', 'hello.bst'])
assert result.exit_code == 0
result = cli.run(project=project, args=['shell', 'hello.bst', '--', 'hello', 'pony'])
assert result.exit_code == 0
assert result.output == 'Hello pony\n'
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment