 Good morning. My name is Van Nantan. I work for CutThink. I work on something called the free desktop SDK, which is a runtime of flat-pack applications. We are trying to use the free desktop SDK for other purposes than just flat-pack, and first I will go to that reason. So we do desktop applications, and for desktop applications it's not like developers are not necessarily Linux experts. They maybe are not Linux developers at all, and they want sometimes to port their existing application to Linux. It's a bit of a problem because on all the platforms you have a unified SDK, and when it comes to Linux, well, this is not working, so there's no Linux SDK. And of course we don't want any unified Linux SDK. It's nice to have a diversity in a Linux platform. But there is a problem then. If this developer who wants to port an application to Linux tries to look at how do I distribute my application, build and distribute an application on Linux, there is a lot of different ways to do it. And many of them are very difficult. You need to be an expert in dynamic linking to understand some of them. And the thing is that if you want to touch a large public, you will need to deploy to several of them. It's not just one. You can't just say I will just make a package for Ubuntu. Well, first, which version of Ubuntu? Because you probably have to rebuild for each version to be safe that it will work everywhere. And it will just be a very small group of users. In this list, in the complete, there is a lot more ways to distribute applications. But here we can see that there are different types. The three ones on top, they use containers. So the two firsts is mostly for this type of application, even though Snap can also distribute services and also what's called, yeah, all this stuff. And Docker is more for backend. But they are very similar. The rest is either difficult to use or difficult to use as a developer. But the problem is that in this first example, there is some fragmentation. And the fragmentation is not about just having several options. Having several options is fine. The problem is that if you want to make an application for Snap users, you will need to use all the tools from Snap. And you won't be able to reuse any of this to make your application work on Flatpak. So this is the issue. So I come back to Free Desktop SDK. So Free Desktop SDK is a user run time for desktop application. So it's something to work on a run time for containers. It's not a distribution. There is no package manager. There is no configuration tools. There is no installation. It's a very basic thing. It's the base for the GNOME SDK and the KDE SDK on Flatpak. And we first target Flatpak, but we want also to target other things. It's built with BuildStream. So BuildStream, what is BuildStream? BuildStream is not the tool that is used for Flatpak to build an application for Flatpak. But we use that for the Free Desktop SDK because it's much more general. So it's a tool for integration of software stacks. It doesn't care about the backend where it will distribute. What it cares is about building. So it has just artifacts. And it's extensible with plugins. So if you really want to have a backend there, you can just add it. So here are the things that we have is that you can also use BuildStream for your application. You use the Free Desktop SDK and you use BuildStream. And you can generate Flatpak repositories or snap files or docker images. I will talk a bit about BuildStream. So BuildStream, how I always use is that you have a project, you make a project and you have lots of elements. And either elements represent one piece of software. For example, you have an element for GCC, an element for binutils, an element for mesadrivers. Elements have dependency between each other. So they are build and run time dependencies. So we have a graph, which can be quite big. But this is used to build an environment to build every step. So for example, if you want to build GCC, you will need to have the binutils as a dependency and it will just make an environment where it will put the binutils for you. You probably also need to have another GCC to build GCC. So you can reproduce builds easily. This is built with bubble wrap, which is a container thing. The artifacts are cached. So once you have built once, you don't have to rebuild unless you change something. So it detects if you have changed something and deserve a rebuild. And it can be also remotely cached. So if you work in a team, that's useful. So you have a graph of lots of elements. When you want to put everything together, we have what we call the integration commands. This is like post-insult script. What we do is just take all the artifacts, flatten everything together, and run all the commands that will just finish the installation of your image. And we do that for every build or every element. We just take all the dependencies and do that. And of course, if you want to check out an artifact, the result of your build, the result of your application, the build of your application, you will get those commands to run and to finish the installation. Another thing that is interesting is that the build stream project can depend on all the build stream project and they can just take elements from the graph, dependency graph from the other project. And we see how it's done. This is an example of an element, how you write an element in build stream. So it's actually not complete. I removed just one part. But this is how to build transmission. Transmission is just a small software for bitter end transfer. You can see that we described it as using the plugin AutoTools on the top, kind. So this will use all the commands that are registered for the AutoTools command. We have plugins for many of the different build systems, but you can make your own plugin easily. Then we have the dependencies. You can see that some are build dependencies. Some don't have any type, and then it means build and run time. And we have also some dependencies that are junctions. So it uses a junction, which is a project that is an upstream project. In this case, we build a transmission of free desktop SDK. So we just import some element from the free desktop SDK. We can set up some variables which is to override some behavior of our plugin. The plugin will use them. So here we just have config parameters. And we have a description of our source. We can hear it's just a simple git, a repository that we get. The last line, which is the commit, is just generated by tracking. So you don't have to type that part. You just have to use a command that puts it for you. You can, of course, have patches and lots of different things. There are lots of different plugins for also the sources. So this is a very simple way to describe how to compile one element. And you have to imagine that you have lots of files that are like that for each of your elements, and they all depend on each other's. So for free desktop SDK, we need three different outputs. And we made some plugins. For each of these outputs that we have, we will have one element that will use one of these plugins. And mainly this will just have a dependency on what we want to put in that image. And also some information on the metadata for that image because the metadata that is in Flatpak application or Snap application or Docker is different. For example, there is no exposed port in Flatpak or maybe there is Snap, but not in Flatpak. There is some in Docker, for example. This is an example of metadata that we need that will be in the element for every of these outputs. So for the Flatpak, we just have two plugins. For those who know the details of Flatpak, we have a Flatpak image which is preparing an image for Flatpak, and then we have another plugin that takes multiple images because Flatpak typically splits application into several images and extensions. So the Flatpak repo will take all your images and put it to one repo. For Snap, we have a very simple plugin which only cares about just putting metadata next to some artifacts because Snap is already very simple. And we use just a generic script to make a Squash FS. For Docker, it's a bit more complex plugin. We have a plugin that makes layers because we want to use layers. We just don't want to check out an artifact and import it right away into Docker because we want to be able to say that an application used for the SAP SDK should be able to use a layer as other applications that use the SAP SDK. And this plugin can either output OCI or Docker one to images. So I will come to the detail of the layering in OCI images because this is the tricky part to understand that thing. So OCI images, Docker images are a stack of layers. For Bitstream, we have a graph. It could be an idea to just say, well, I've flattened my graph and then get all my layer, one layer per element, but this is not possible. And the reason is that if you flatten two different graphs that have command elements, the order of those elements in the stack will be different and might be some elements that are also missing. So while the identifiers of the layers itself will be the same, if you look at the implementation of Podman or Docker, the way it will be stored on disk or on the server will be using probably some chain ID, which is depending on also the layers on top of it. So we can use it and also we have a lot of elements and Docker is not really meant for using a lot of elements, especially we have some backend drivers that might not be able to have layering on many, many layers. So instead, we forward the users to say exactly what they want. But we provide this layering, but you have to be explicit about how you do this layering. This is an example. So this is how the layers we have decided to make them in Fredesta-Pesique. So when simplified the graph, because the graph is big and doesn't get in the slide, so we adjusted some elements that are the SDK, the platform and the bootstrap, which are three different layers of the, or for general layers of SDK. And next to that, I've made some elements that represent the different things that I want to have as OCI. OCI layers. Not that we don't distribute all of them as an image, the bootstrap is not distributed, but it will be used just to make a layer that would be reused by other elements. So here we can see that Platform OCI, for example, will take Platform BST, it will take the artifact, and it will also use the bootstrap OCI and compare the two layers, the two artifacts, and build a layer out of the platform BST that will go on top of bootstrap OCI. And every element will represent a layer and an image as well. So for every layer, you make an element. If you have an application, so here, for example, Transmission Daemon, which fits very well with Docker, we can... This is another project that uses Freelancer SDK, because with the Junction, we can just reuse... We can reuse the elements from the upstream project, which is Freelancer SDK. We can just say, I want to make a layer on top of my bootstrap layer in this case, but I could also use the Platform. Yes. That was it for how it works. That was the tricky part. So the current state of it, we push the Docker images to the Docker hub. You can also just build yourself easily and fetch from the cache the images using build stream. For Flatpak, of course, we have always supported that, so we distribute that since I'm in time. For Snap, we have something that is missing, but it's soon there. I have made some examples using Firefox and Transmission to show how to do this kind of thing. So Firefox doesn't provide any Docker images, because Docker is not very good for pure desktop application, but I have another example, which is Transmission. Transmission comes with a different output. There is a GTK front-end, there's command lines, and there is a daemon that is just a web interface. If you want the slides, by the way, you can just go on the program and the slides are put there. Firefox is a very good example because it's a big application that is very annoying to build several times, so you really want to build only ones for different back-ends. So those are just examples. This is to show how we can do it, and I would love to have feedback from that if you think that there is problems. If you want to do your own application and distribute on different things, just look at those. So as I said, we had some problems with Snap, so for Snap we just wait for one bug to be... not one bug, one feature to be added in Snap. For the month, the strict confinement doesn't work for us. This is something that will be fixed by the end of the year in Snap, so you can start to use it unless you really want to distribute something right now, but it's coming. Also, there are things that we have to look at, for example, the way slashetc is dealt with Flatpak and SnapD. The NVidia drivers have not been tested in Snap, so that's something I need to do, but I need to have a machine with NVidia. We don't have equivalent of Flatpak extension in OCI or SnapD, and also we have something missing in BlueStream to deal with having multiple users in an image, which would be interesting for OCI images. That's something that we need to address. Yes, any question? Okay, so you've sort of shown how BuildStream works. If I were completely new to this, where do I get it? How do I run it? I probably should have put a link. It's on GitLab, so if you go on gitlab.com slash buildstream, you will find it. There's actually buildstream.build as well. There will be also documentation on how to install. It's a Python project, so you can install it normally with pip, if you want, pip install buildstream. Yes, it's packaged in some distributions. I think Fedora is packaged. Actually, lots of ones. It's all described in this documentation. Buildstream.build. I should have put that link. It was not clear to me how you distinguish between what you're building or for which thing you're building. If you have to specify the slash app prefix for Flatpak, how do you distinguish that in the manifest for BuildStream? I'm sorry, what was the example that you said? You want to compile a few dependencies, for Flatpak, sometimes you have to, whatever is the build system for the dependency, you have to put slash app as a prefix. How do you distinguish between Snap and Flatpak? Interesting question. The way it's done is for Snap, you can re-bind things. The way you make applications, the examples bind the application directory into slash app. For OCI, it's not a problem. You just can put it there. You should build your application in slash app. It's not a free stop. It's just to be compatible. If you want to also put for Flatpak, you will need to have slash app. Yeah, but just, I mean, in the case that you... So you have to have your dependency compiled already for slash app. Is that the case? I'm sorry. Yeah, everything is built with this, but yeah, your application is built with knowing that the prefix is slash app. You have to do that, but it's not very difficult. I mean, just your project to just say, my prefix is slash app, and all the plugins will take it. And you will build everything there. So it's really made to be used with the free stop SDK, right? It's not made to be distributed outside of the free stop SDK runtime. So you build for slash app. Yeah, I mean, I'll let... Maybe we can talk about that because I think it's time. Okay, so thank you very much.