Posts

Testing Mesa ACO with Flatpak

Valve has been asking users to help with testing the ACO patches for Mesa. It replaces LLVM to compile shaders.

Testing a development or patched version of Mesa is not necessarily easy. So in order to help users in doing testing we are building an extension for the upcoming Freedesktop SDK 19.08. No need to build anything. Just install and define FLATPAK_GL_DRIVERS to select the patched version of Mesa.

And good news: the Flatpak application for Steam has now a beta release working with 19.08beta of Freedesktop SDK.

However we do not deliver the ACO+Mesa extension to flathub. So you will need to get it from our development release server.

So here is the procedure. First install the runtime and the mesa extensions:

flatpak remote-add --user freedesktop-sdk https://cache.sdk.freedesktop.org/freedesktop-sdk.flatpakrepo
flatpak install --user freedesktop-sdk \
    org.freedesktop.Platform//19.08beta \
    org.freedesktop.Platform.GL.mesa-aco//19.08beta \
    org.freedesktop.Platform.GL32.mesa-aco//19.08beta \
    org.freedesktop.Platform.GL32.default//19.08beta \
    org.freedesktop.Platform.Compat.i386//19.08beta

Then install Steam’s beta Flatpak app (it is not the beta of Steam, just the Flatpak app).

flatpak remote-add --user flathub-beta https://dl.flathub.org/beta-repo/flathub-beta.flatpakrepo
flatpak install --user flathub-beta com.valvesoftware.Steam//beta

To run it, make sure Steam is not already running. Then:

FLATPAK_GL_DRIVERS=mesa-aco flatpak run com.valvesoftware.Steam//beta

You should see somewhere in the console the following message:

WARNING: Experimental compiler backend enabled. Here be dragons! Incorrect rendering, GPU hangs and/or resets are likely

If you see it, you are all set. And you can start testing. Remember you can set RADV_PERFTEST=llvm as environment variable to disable ACO if you want to compare.

Please follow the ACO testing instructions.

If you are using flatpak to test, please report issues to us before, either on IRC (#freedesktop-sdk on Freenode) or on our issue tracker. We can make sure the issue is not an issue on our side.

Freedesktop SDK cross compilers

In upcoming Freedesktop SDK 19.08 release, we will introduce cross compilers. x86-64 will be able to cross-compile to all other available architectures. aarch64 will be able to cross-compiler to armv7.

Motivation

Legacy 32-bit support

Freedesktop SDK does not provide support for multilib. Multilib is having /usr/lib and /usr/lib64 as library directories and support for -m32 in GCC.

In order to support applications providing both 64-bit and 32-bit binaries, the 32-bit library directory was mounted in a different directory. The original path of 32-bit libraries would conflict with the path of the 64-bit ones. So the 32-bit library were in a directory that they were not intended to be. This directory was added in LD_LIBRARY_PATH originally, and later in ld.so.cache.

However, due to recurrent issues with some 32-bit games in Steam, multiarch library paths were introduced in the 18.08 release. The library directories are like like /usr/lib/x86_64-linux-gnu. Multiarch comes from Debian. It is a solution that is more generic than multilib, more future-proof, and cross-compilation and emulation friendly.

32-bit runtime is extracted from the 32-bit build, and then added to at the right library path as an extension to the 64-bit runtime.

Unfortunately, applications needing to build extra 32-bit libraries that were not in the Freedesktop SDK would have needed some complicated hacks when using Flatpak Builder. This is because -m32 is not supported. The 32-bit libraries need to be built with the 32-bit SDK and then extracted and reimported.

Providing a cross-compiler as well as a multiarch SDK would solve this issue.

Steam was the only application needing 32-bit support. At first, no extra 32-bit runtime that was not in Freedesktop SDK was required. This has changer. Also now Lutris, which is available as beta Flatpak application on Flathub requires 32-bit Wine and is waiting for 32-bit cross-compilers.

Building applications for smaller devices

Phones, tablets and netbooks often use ARM. But developers typically develop on x86-64. Most developers do not own an ARM board to build their applications.

For now, those who wanted to test building Flatpak applications for ARM needed to use QEMU. The issue is that running the compiler on emulation is potentially slow. And it is not unlikely that applications need to build some big libraries like WebKit. This would take an awful long time.

Cross-compile with FlatpakBuilder

Let’s say we want to cross-compile GNU Hello, from an x86_64 machine to aarch64.

First we need to install the 19.08 SDK. This will come soon as beta on flathub. But for the moment, we can add remote https://cache.sdk.freedesktop.org/freedesktop-sdk.flatpakrepo

We will need to install:

  • org.freedesktop.Sdk//19.08, the build SDK.

  • org.freedesktop.Sdk.Extension.toolchain-aarch64//19.08, the cross compiler extension. It contains mostly the linker and the compiler.

  • org.freedesktop.Sdk.Compat.aarch64//19.08, the SDK for the target runtime. This contains the libraries to link to, the pkg-config files, and the architecture dependent headers.

  • org.freedesktop.Platform/aarch64/19.08, the target runtime. This is not used to build, but it is required to be installed by Flatpak Builder.

We will then create file org.gnu.Hello.yml:

app-id: org.gnu.Hello
# We need to force here the target architecture for the runtime
runtime: org.freedesktop.Platform/aarch64
runtime-version: '19.08'
# To avoid confusion we can set the architecture for the SDK. But this is
# not important.
sdk: org.freedesktop.Sdk/x86_64
command: hello
sdk-extensions:
# We need to ensure the toolchain is available
- org.freedesktop.Sdk.Extension.toolchain-aarch64
# As well as the target SDK
- org.freedesktop.Sdk.Compat.aarch64

modules:
  - name: hello
    buildsystem: autotools
    build-options:
      # Add the cross compiler to the PATH
      append-path: /usr/lib/sdk/toolchain-aarch64/bin
      # binutils are available there in a different path. GCC knows
      # where to get them. But if we need access to those tools,
      # they can be added to the path that way:
      # prepend-path: /usr/lib/sdk/toolchain-aarch64/aarch64-unknown-linux-gnu/bin

      # In this case we do not need pkg-config. But if needed,
      # we can add this path:
      # prepend-pkg-config-path: /usr/lib/aarch64-linux-gnu/pkgconfig
      env:
        # Because default CFLAGS are architecture-specific, we need
	# to reset them to something more portable.
        CFLAGS: -g -O2
        CXXFLAGS: -g -O2
      config-opts:
      # This is a standard option for autoconf to cross-comile
      - --host=aarch64-unknown-linux-gnu
    sources:
      - type: archive
        url: https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz
        sha256: 31e066137a962676e89f69d1b65382de95a7ef7d914b8cb956f41ea72e0f516b

With this we can now build our application.

# We build and commit the app in repo/
flatpak-builder build org.gnu.Hello.yml --repo=repo

# We create a new repository containing the commits for aarch64
ostree init --mode archive-z2 --repo=aarch64-repo

for i in app/org.gnu.Hello \
         runtime/org.gnu.Hello.Debug \
	 runtime/org.gnu.Hello.Locale
do
     # We rename the commits to for them to be for aarch64
     flatpak build-commit-from \
        --src-ref=${i}/x86_64/master \
	--src-repo=repo \
	aarch64-repo \
	${i}/aarch64/master
done

# Now we can create a bundle for our application
flatpak build-bundle --arch=aarch64 \
                     aarch64-repo \
		     org.gnu.Hello-aarch64.bundle \
		     org.gnu.Hello

We will then get a bundle called org.gnu.Hello-aarch64.bundle. We can transfer it to a device to be installed and tested.

Cross-compile with BuildStream

Let’s do the same exercise but using BuildStream instead.

To cross-compile in BuildStream, cross-compilers/gcc-<arch>.bst needs to be used. The runtime also needs to be imported. For the moment only the standard runtime is provided (glibc, GCC’s libstdc++ and GCC’s runtime). This is because BuildStream does not allow yet to import artifacts built from different architectures. For our example, GNU Hello, we do not need anything else than glibc and GCC’s runtime. This runtime is available from cross-compilers/standard-libs-<arch>.bst

Here is the project.conf.

name: hello
ref-storage: project.refs

variables:
  # Application files should be installed in /app for flatpak applications
  prefix: /app

  # Debugdir is still unchange, we will extract files at the right place
  debugdir: /usr/lib/debug

# We enable flatpak related plugins
plugins:
- origin: pip
  package-name: buildstream-external
  elements:
    flatpak_image: 0
    flatpak_repo: 0

environment:
  # We add the aarch64 toolchain in the path
  # If some tools use binutils without querying `gcc -print-prog-name`,
  # we can add `/usr/lib/sdk/toolchain-aarch64/aarch64-unknown-linux-gnu/bin`.
  PATH: '/usr/lib/sdk/toolchain-aarch64/bin:/usr/bin'

  # In theory we should add pkg-config path. In practice,
  # we do not yet have the runtime available on BuildStream.
  PKG_CONFIG_PATH: '/usr/lib/aarch64-linux-gnu/pkgconfig:'

elements:
  # Autotools supports cross-compilation out of the box. We enable it
  # by default for all our elements.
  autotools:
    conf-global: >-
      --build=x86_64-unknown-linux-gnu
      --host=aarch64-unknown-linux-gnu

The Freedesktop SDK junction freedesktop-sdk.bst:

kind: junction

config:
  options:
    bootstrap_build_arch: "x86_64"
    target_arch: "x86_64"

sources:
- kind: git
  url: https://gitlab.com/freedesktop-sdk/freedesktop-sdk.git
  track: master

And here is the element hello.bst.

kind: autotools

depends:
- filename: public-stacks/buildsystem-autotools.bst
  junction: freedesktop-sdk.bst
  type: build

  # This is the cross-compiler
- filename: cross-compilers/gcc-aarch64.bst
  junction: freedesktop-sdk.bst
  type: build

  # This is the aarch64 runtime to which we need to link
- filename: cross-compilers/standard-libs-aarch64.bst
  junction: freedesktop-sdk.bst
  type: build

sources:
- kind: tar
  url: https://ftp.gnu.org/gnu/hello/hello-2.10.tar.gz

The main flatpak element org.gnu.Hello.bst:

kind: flatpak_image

depends:
- filename: hello.bst
  type: build

config:
  directory: '%{prefix}'
  exclude:
  - debug

  metadata:
    Application:
      name: org.gnu.Hello
      runtime: org.freedesktop.Platform/aarch64/19.08
      sdk: org.freedesktop.Sdk/aarch64/19.08
      command: hello

    'Extension org.gnu.Hello.Debug':
      directory: lib/debug
      autodelete: true
      no-autodownload: true

The debug extension element org.gnu.Hello.Debug.bst:

kind: flatpak_image

depends:
- filename: hello.bst
  type: build

config:
  directory: '%{debugdir}%{prefix}'

  metadata:
    Runtime:
      name: org.gnu.Hello.Debug

    ExtensionOf:
      ref: 'app/org.gnu.Hello/x86_64/master'

And finally the flatpak repository flatpak-release-deps.bst:

kind: flatpak_repo

depends:
- filename: org.gnu.Hello.bst
  type: build
- filename: org.gnu.Hello.Debug.bst
  type: build
- filename: deploy-tools/flatpak.bst
  junction: freedesktop-sdk.bst
  type: build

config:
  arch: aarch64
  branch: master

  environment:
  - deploy-tools/flatpak.bst

In order to build and bundle our application we now need to run the following commands.

# First we need to track separately junctions.
bst track freedesktop-sdk.bst
# Then we track our elements.
bst build --track hello.bst
# We build the flatpak repository and extract it
bst build flatpak-repo.bst
bst checkout flatpak-repo.bst repo

# We then convert the repository to a bundle
flatpak build-bundle --arch=aarch64 \
                     repo \
		     org.gnu.Hello-aarch64.bundle \
		     org.gnu.Hello

We will then get a bundle called org.gnu.Hello-aarch64.bundle similar to the one built with the FlatpakBuilder method.

Aknowledgements

This work has been sponsored by Codethink Ltd.

Building applications for both Snappy and Flatpak at once

I am going to show here how it is possible to build an application for Snappy and Flatpak at the same time.

This is not about converting Flatpak to run on Snappy.

Motivation

Flatpak and Snappy are both package management systems where applications come with their userland runtime. This is allows those applications to run on any distribution.

With Snappy and Flatpak, developers can finally distribute their applications without a need to build for multiple distributions (and multiple versions of them).

However both Snappy and Flatpak both come with their development tools, respectively Snapcraft and FlatpakBuilder. The choice of the developer’s tool affects what the user is going to use. This forces users to have both Snappy and Flatpak installed.

But since the applications come with their own userland runtime, the same build should be able to be packaged for both Snappy and Flatpak.

Base runtimes

Applications runtimes are not fully built from scratch. A base system is needed to build the rest on top of it.

Snappy applications run on Ubuntu Core. Ubuntu Core is very minimal. When building the application, dependencies can be built from source, or imported from prebuilt packages.

Flatpak applications run on Freedesktop SDK. Freedesktop SDK contains the minimum runtime to run a desktop application. Other runtimes are also available: Gnome or KDE. Those are built on top of Freedesktop SDK. Other dependencies can be built from sources.

To be able to run an application built on both Flatpak and Snappy, you need to be able to use the same base runtime on both. As a developer of Freedesktop SDK, I have been looking shipping it to Snappy. However, it should be possible to do the same work on Ubuntu Core to run on Flatpak.

BuildStream

Since version 18.08, Freedesktop SDK is being built with BuildStream rather than FlatpakBuilder. BuildStream is also used to build the Gnome SDK.

BuildStream is independent from Flatpak. There is nothing Flatpak specific about it. We use plugins in order to generate Flatpak packages.

For that reason we can also use BuildStream to build bootable images, OCI/Docker images, and Snappy images.

Demo

As a demonstration, I made a build of Firefox.

The source code for the build is available at https://gitlab.com/valentindavid/firefox-buildstream.

Structure

The main file to build Firefox itself is elements/firefox.bst. We also need to build dependencies and package the application. Here is a description of the directory structure of the project.

  • elements/freedesktop-sdk.bst Describe which version of Freedesktop Sdk we depend on.
  • elements/ Contains .bst files describing how to compile firefox and dependencies.
  • elements/snap/ Contains element files describing how to package the application for Snappy.
  • elements/flatpak/ Contains element files describing how to package the application for Flatpak.
  • files/ contains extra source files.
  • patches/ contains patches referenced by elements.
  • plugins/ contains extra BuildStream plugins.
  • app.yml is the generic BuildStream configuration for application.
  • project.conf is the BuildStream configuration for this application.

Note that many files will be common to every application and will be either merged to Freedesktop SDK or bst-external (the BuildStream plugin collection).

Prerequisites

You will need to install BuildStream 1.2 and bst-external. One way to do it is:

pip3 install --user git+https://gitlab.com/BuildStream/buildstream.git@bst-1.2
pip3 install --user git+https://gitlab.com/BuildStream/bst-external.git@master

There are other ways to install it. Please read the BuildStream’s installation page for more information.

Building and installing Freedesktop SDK as snap

git clone https://gitlab.com/freedesktop-sdk/freedesktop-sdk.git freedesktop-sdk-snap --branch valentindavid/snap
cd freedesktop-sdk-snap
make export-snap
snap install --dangerous snap/platform.snap

Do not worry, this will download already built artifacts from the Freedesktop SDK cache server.

Building and testing Firefox

First we will build Firefox itself.

git clone https://gitlab.com/valentindavid/firefox-buildstream.git
cd firefox-buildstream
bst build firefox.bst

This will take some time. Some dependencies not in Freedesktop SDK as well as Firefox itself will need to build. Of course applications can use artifact cache servers to speed up build time.

Now we can run it directly with BuildStream to test it.

bst shell firefox.bst -- firefox --new-instance

The container will run with an empty fresh home directory. So it will not affect your existing Firefox profiles.

And it should run:

Firefox on "bst shell"

In order to do some debugging, you can create a new element that depends on firefox.bst as well as your required debugging tool from Freedestkop SDK, for example gdb.bst. After building it, just bst shell that element.

kind: stack
depends:
- filename: base/gdb.bst
  junction: freedesktop.bst
- filename: firefox.bst

Building the snap package

To build, install and run Snappy packages:

bst build snap/image.bst
bst checkout snap/image.bst snap/
snap install --dangerous snap/firefox.snap
/snap/bin/firefox --new-instance

Elements related to making a snap elements are in directory elements/snap.

Element snap/firefox.bst creates a directory ready for Snappy with the meta/snap.yaml file. We do not provide a static file for meta/snap.yaml as we may use BuildStream variables to be expanded.

Element snap/image.bst takes this directory and builds a proper .snap file using mksquashfs.

Building the flatpak package

To build, install and run Flatpak packages:

bst build flatpak/repo.bst
bst checkout flatpak/repo.bst repo/
flatpak remote-add --no-gpg-verify local-firefox repo/
flatpak install local-firefox org.mozilla.Firefox

It is possible to export a bundle. Please see the documentation.

Elements related to building the Flatpak are in elements/flatpak.

The main element is flatpak/org.mozilla.Firefox.bst which builds the built directory for flatpak.

This element is then taken in flatpak/repo.bst which creates a flatpak repository using flatpak build-export (It is Flatpak, not FlatpakBuilder).

Application path

Flatpak applications expect to be mounted at /app. However, this is not the case with Snappy where it is available at $SNAP. Flatpak runs ldconfig on application with /app/lib activate. For Snappy, wrapper scripts are used to set LD_LIBRARY_PATH to $SNAP/lib. For loading library that works.

When it comes to other data to load however, the application needs to be aware of the path. The wrapper may define more paths using environment variables. But the application itself needs to be able to read them. That might mean modifying it, and patching some dependencies.

Current status

At the time of writing the work is a merge request being reviewed on the Freedesktop SDK.

The CI is ready to publish the Freedesktop SDK runtime as soon as we have a new release. There will also be edge builds automatically pushed at each new merge. The name is reserved to be https://snapcraft.io/freedesktop-sdk-runtime-18-08.

Because the Freedesktop SDK runtime is of “base” type, it will require manual review from Snapcraft. I am waiting for finished review from Freedesktop SDK before requesting one on Snapcraft’s store.

Challenges and work ahead

The image of Freedesktop SDK for Snappy is soon ready to publish. But there is still work ahead. I will give here a list of things I have in mind that need to be done.

snap-confine and /etc

snap-confine mounts /etc from host. And it remounts few exceptions from the runtime image. Flatpak does the opposite by it takes most of things from /etc from the image but has few exceptions taken from host or generated.

Freedesktop SDK has been made for Flatpak and for example, font configuration in /etc/fonts is expected to be from the image to match the fonts we provide.

It would be possible to selectively tell packages to use /etc or /usr/etc depending whether they want to read respectively host or image configuration. But this will be some work. We will probably fix it case by case when bugs are filed.

For the Firefox demo, we worked around the font issue by copying /etc/fonts in the application image, and defined FONTCONFIG_PATH in the wrapper script.

Forced to provide Dash

snap-confine uses apparmor. snap-confine will run /bin/sh and expects it to be Dash. That forces use to provide Dash as /bin/sh on the Snap version of the Freedesktop SDK. We would like of course that snap-confine lets us use what Bourne Shell we want.

BuildStream boiler-plate

Because BuildStream is very generic it can be relatively verbose. However applications will have mostly the same configuration and plugins.

We have added support for configuration import through external projects for this purpose. So soon we should see application configuration provided directly by the Freedesktop SDK.

Nvidia proprietary drivers

I have not dealt with Nvidia proprietary drivers yet. My understanding is that snap-confine mounts them. Freedesktop SDK already dispatches with libglvnd, the Vulkan loader, and OpenCL loader. Drivers in flatpak are provided through extensions. So I am guessing it will need some tweaks for the paths.

KDE and Gnome SDKs to Snappy

The Gnome SDK is already using BuildStream, so once we have a relatively stable Snap version of Freedesktop SDK, we will look at providing this GNOME Build Meta.

KDE SDK is still built using FlatpakBuilder. So it would need to be rewritten using BuildStream.

Aknowledgements

This work has been sponsored by Codethink Ltd.

LAS

I recently went to Libre Application Summit (LAS) 2018 in Denver, CO. I went there to present the release of Freedesktop SDK 18.08 along with Tom Coldrick, Adam Jones.

There were plenty of interesting talks. I will not cover everything. But I would like here to talk about what I took out of it.

One of the interesting part of the conference was the different talks given from Aleix Pol and Albert Astals Cid from KDE. We got an interesting overview of their views, their process and what they provide to both users and developers. It is important for the developer to reach the user and address their needs and that promptly. The release process of KDE applications is very intensive with a cycle of only four months. Discover, their application installation interface, gives the choice to the user what application backend to use: distribution package, Flatpak or Snap. While they still prefer the distribution packages, it seems it is something that might change. The reason mentioned was the issues due to PPAs. This sounds like a good move.

This is in contrast with what Elementary OS is doing. Cassidy James Blaede and Daniel Foré presented their view of a more homogeneous application ecosystem where technologies are recommended to developers to provide a better experience for both the developer and the user. They are slightly more controversial and try to rethink software development approaches open-source has been using for a long time. While I am not sure all will be popular in FOSS, I am looking forward to the positive outcomes of this experiment. One thing interesting from their side is the monetization of FOSS applications, the way to remind users that “free” software means freedom, but they should still pay (what they want) for software.

From Endless, Matthew Leeds talked about Flatpak application distribution through USB keys and local network. This was interesting and technical. The architectural design is well thought. The user experience shown during the demo at the end seems very good.

Other interesting Flatpak technical talk was Alex Larrson’s technical walk-through of Flatpak. This was interesting and this is the kind of talk I wished I had heard before submitting my first patch to Flatpak. This was very simple and still covered a lot. I recommend watching the video.

On the side of user perspective we had interesting feedback by Ryan Gorley from FreeHive on the state of free software for digital artists. It is interesting to have the testimony of a professional on the use of raster/vector graphics editors, 3D modelers, sound editors, etc. He also provided his view on how to make FOSS more popular. Interestingly, several points were quite ideological about FOSS, which I do not think most of users care about. But in his view FOSS can make the user feel empowered.

Looking forward to LAS 2019.