Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for building Flatpak bundles #512 #5711

Merged
merged 4 commits into from Apr 8, 2021

Conversation

vially
Copy link
Contributor

@vially vially commented Mar 14, 2021

Add a new Linux target for exporting applications in Flatpak format.

Implementation details

The current implementation is delegating the actual build process to @malept/flatpak-bundler, which is a Node wrapper over the flatpak-builder tool.

Similar to the other Linux targets (e.g.: AppImage, snap, etc) the Flatpak target allows the user to customize some of the options. However, in order to make it as easy as possible to get started, some sensible defaults are also provided out-of-the-box:

[
    // Wayland/X11 Rendering
    "--socket=wayland",
    "--socket=x11",
    "--share=ipc",
    // Open GL
    "--device=dri",
    // Audio output
    "--socket=pulseaudio",
    // Read/write home directory access
    "--filesystem=home",
    // Allow communication with network
    "--share=network",
    // System notifications with libnotify
    "--talk-name=org.freedesktop.Notifications",
]

Also, an electron-wrapper script is automatically added to the bundle which uses zypak for sandboxing the applications.

When the electron version supports it (version 12 and above), the Wayland flags (--enable-features=UseOzonePlatform --ozone-platform=wayland) are also automatically added to this wrapper script in order to provide a better out-of-the-box experience for Wayland users.

Limitations and possible future work

Note: This pull-request only makes it possible to export *.flatpak bundles.

In the future, it might make sense to also implement a Flatpak publisher (similar to the Snap Store publisher) that makes it possible to publish the application to a repository (e.g.: Flathub).

However, it's not entirely clear how that would work so it is not part of this pull-request. But it is something that should be considered as a possible next step.

Related issues: #512

@vially vially mentioned this pull request Mar 14, 2021
@vially
Copy link
Contributor Author

vially commented Mar 21, 2021

FYI I've rebased and force-pushed to fix some small conflicts introduced by the recent migration from Yarn to pnpm (#5710).

@vially vially force-pushed the add-flatpak-support branch 2 times, most recently from 9ffc66f to ec72ef4 Compare March 31, 2021 18:39
@mmaietta
Copy link
Collaborator

mmaietta commented Apr 5, 2021

Hi @vially! Thanks for the contribution!
We should have some tests to back this up, something like these: https://github.com/electron-userland/electron-builder/tree/master/test/src/linux

You might be able to literally just copy one of the test files and switch up the target to flatpak

@mmaietta mmaietta self-assigned this Apr 5, 2021
@vially
Copy link
Contributor Author

vially commented Apr 6, 2021

@mmaietta Thanks for the feedback!

I added some tests (da167a1) and a fix for an issue uncovered by the tests (d7d2f78).

I think it's worth mentioning that these tests are really slow. On my machine it's taking around 5 minutes just for these Flatpak tests to run. For what it's worth it's pretty close to what I get when running the underlying flatpak-builder commands directly, so I don't think this is due to some overhead introduced in electron-builder.

I'm not sure what would be considered a reasonable time frame for these tests, but it may be worth considering disabling them by default if you think this is unacceptable (similar to these snap tests).

@mmaietta
Copy link
Collaborator

mmaietta commented Apr 8, 2021

Thanks for adding the tests!

I'll need to figure out a way for us to get some more build node coverage for these heavy tests (similar as was done for mas and dmg tests)

@refi64 you're our resident expert! 😉 Could you run a final review please?

@refi64
Copy link

refi64 commented Apr 8, 2021

😅 I'm admittedly not too familiar with electron-builder, but at a glance everything here does seem to check out.

@mmaietta
Copy link
Collaborator

mmaietta commented Apr 8, 2021

I joined the maintainer crew only a month or so ago 😅

Thanks for reviewing the flatpak implementation! That helps a lot.
Might reach out to you in the future if any issues show up because I'm unfamiliar in this subject. If you wouldn't mind, can you officially hit the "approve" button on the PR?

@refi64
Copy link

refi64 commented Apr 8, 2021

Done!

@mmaietta mmaietta merged commit 6b1be73 into electron-userland:master Apr 8, 2021
@mmaietta
Copy link
Collaborator

mmaietta commented Apr 8, 2021

@vially would you be willing to also add documentation for this new feature to electron-builder docs branch?

@vially
Copy link
Contributor Author

vially commented Apr 9, 2021

would you be willing to also add documentation for this new feature to electron-builder docs branch?

I think I may need some assistance in doing that. Just to make sure I'm on the right track here, the documentation is supposed to be auto-generated from the TypeScript comments and/or the schema, right?

If that's the case then I must be doing something wrong because I didn't manage to get the scripts to run. I also get the feeling the documentation may not be entirely up-to-date.

These are some of the things I tried that didn't work:

mkdocs build

Out of the box it fails with an error complaining about the usage of IP address 0.0.0.0. Once I change that to 127.0.0.1 it gets past that error but it now fails with a Python stack-trace ending with: AttributeError: 'dict' object has no attribute 'split'.

Maybe an older version of mkdocs and/or Python should be used (I've only tried with mkdocs 1.1.2 and Python 3.9.2)?

pnpm run docs

Initially it fails with some errors complaining about some missing node modules (source-map-support and path-sort). Once I get past those (pnpm add -D path-sort source-map-support -w) then the jsdoc2md step fails with lots of errors (e.g.: ERROR: Unable to parse a tag's type expression for source file...) pointing to JSDoc comments that look like Platform<> (supposedly because this is invalid JSDoc code?).

For example, this is one such problematic comment taken from ./scripts/jsdoc/out/builder/electron-builder.js:

/**
 * @param {Array<Platform<>>} platforms
 * @param {string | "undefined"} type
 * @param {string | "undefined"} arch
 * @returns {Map<Platform<> | Map<Arch | Array<string>>>}
 */
export function createTargets() {}

So, my main question is, are these actually the right commands for generating the documentation? And if they are, can anyone confirm that they have been able to run them recently on the master/docs branches?

@razzeee
Copy link

razzeee commented Mar 12, 2022

It would be really handy, if this was documented

@alariej
Copy link

alariej commented Mar 14, 2022

Documentation of FlatpakOptions (https://www.electron.build/configuration/configuration.html#FlatpakOptions) would definitely be great. In the meantime, a simple example config file could be very useful. Has someone found one already?

@mmaietta
Copy link
Collaborator

https://www.electron.build/api/programmatic-usage for a js/scripted configuration

@alariej
Copy link

alariej commented Mar 15, 2022

@mmaietta Thanks for coming back. I had seen this example, but it unfortunately doesn't contain any specific configuration for producing a flatpak build. And the link https://www.electron.build/configuration/configuration.html#FlatpakOptions seems to be pointing nowhere.

I've nevertheless tried to run electron-builder --linux flatpak --config builder-flatpak.json where builder-flatpak.json contains:

{
    "appId": "chat.quadrix",
    "productName": "quadrix",
    "linux": {
        "category": "Internet",
        "target": [
            "flatpak"
        ],
        "icon": "src/resources/logos/logo256.png"
    },
    "flatpak": {
        "description": "Minimal, simple, multi-platform chat app for the Matrix protocol"
    },
    "files": [
        "dist-web/**/*",
        "electron-main.js"
    ],
    "directories": {
        "output": "dist/"
    }
}

With this minimal config, I get the following output / error:

  • electron-builder  version=22.14.13 os=5.13.0-35-generic
  • loaded configuration  file=/home/.../quadrix/builder-flatpak.json
  • writing effective config  file=dist/builder-effective-config.yaml
  • packaging       platform=linux arch=x64 electron=17.1.2 appOutDir=dist/linux-unpacked
  • building        target=flatpak arch=x64 file=dist/quadrix-0.6.4-x86_64.flatpak
  ⨯ flatpak failed with status code 1  failedTask=build stackTrace=Error: flatpak failed with status code 1
    at ChildProcess.<anonymous> (/home/.../quadrix/node_modules/@malept/flatpak-bundler/index.js:71:16)
    at ChildProcess.emit (node:events:390:28)
    at maybeClose (node:internal/child_process:1064:16)
    at Process.ChildProcess._handle.onexit (node:internal/child_process:301:5)

flatpak-builder was installed on my Ubuntu system with sudo apt install flatpak-builder (which installed version 1.0.14)

As you can see, I'm new to flatpak, so I'm kind of stuck here at the moment. Any help or link to relevant info would be appreciated.

@mmaietta
Copy link
Collaborator

Interesting that it's not linking anywhere on the website. Here's the interface/options for the flatpak config to get you in the right direction

export interface FlatpakOptions extends CommonLinuxOptions, TargetSpecificOptions {
/**
* The path to EULA license file. Defaults to `license.txt` or `eula.txt` (or uppercase variants). Only plain text is supported.
*/
readonly license?: string | null
/**
* The name of the runtime that the application uses. Defaults to `org.freedesktop.Platform`.
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly runtime?: string
/**
* The version of the runtime that the application uses. Defaults to `20.08`.
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly runtimeVersion?: string
/**
* The name of the development runtime that the application builds with. Defaults to `org.freedesktop.Sdk`.
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly sdk?: string
/**
* Start with the files from the specified application. This can be used to create applications that extend another application.
* Defaults to [org.electronjs.Electron2.BaseApp](https://github.com/flathub/org.electronjs.Electron2.BaseApp).
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly base?: string
/**
* Use this specific version of the application specified in base. Defaults to `20.08`.
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly baseVersion?: string
/**
* The branch to use when exporting the application. Defaults to `master`.
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly branch?: string
/**
* An array of arguments passed to the flatpak build-finish command. Defaults to:
* ```json
* [
* // Wayland/X11 Rendering
* "--socket=wayland",
* "--socket=x11",
* "--share=ipc",
* // Open GL
* "--device=dri",
* // Audio output
* "--socket=pulseaudio",
* // Read/write home directory access
* "--filesystem=home",
* // Allow communication with network
* "--share=network",
* // System notifications with libnotify
* "--talk-name=org.freedesktop.Notifications",
* ]
* ```
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly finishArgs?: string[]
/**
* An array of objects specifying the modules to be built in order.
*
* See [flatpak manifest documentation](https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest).
*/
readonly modules?: (string | any)[]
/**
* Files to copy directly into the app. Should be a list of [source, dest] tuples. Source should be a relative/absolute path to a file/directory to copy into the flatpak, and dest should be the path inside the app install prefix (e.g. /share/applications/).
*
* See [@malept/flatpak-bundler documentation](https://github.com/malept/flatpak-bundler#build-options).
*/
readonly files?: [string, string][]
/**
* Symlinks to create in the app files. Should be a list of [target, location] symlink tuples. Target can be either a relative or absolute path inside the app install prefix, and location should be a absolute path inside the prefix to create the symlink at.
*
* See [@malept/flatpak-bundler documentation](https://github.com/malept/flatpak-bundler#build-options).
*/
readonly symlinks?: [string, string][]
/**
* Whether to enable the Wayland specific flags (`--enable-features=UseOzonePlatform --ozone-platform=wayland`) in the wrapper script. These flags are only available starting with Electron version 12. Defaults to `false`.
*/
readonly useWaylandFlags?: boolean
}

@cbartondock
Copy link

Just in case it helps anyone I was able to build flatpaks while getting essentially get all the benefits of using electron-builder (e.g. native module support) using an additional step in the build process with @malept/electron-installer-flatpak. The relevant npm scripts are:

  "scripts": {
    "postinstall": "electron-builder install-app-deps",
    "build:main": "cross-env NODE_ENV=production webpack --config ./webpack/main.js",
    "build:renderer": "cross-env NODE_ENV=production webpack --config ./webpack/renderer.js",
    "build:dist": "rimraf dist && npm run build:main && npm run build:renderer",
    "build:linux": "electron-builder --linux --ia32 --x64 --dir && cp LICENSE release/linux-unpacked/ && cp electron-version release/linux-unpacked/version",
    "build:flatpak": "electron-installer-flatpak --src release/linux-unpacked --dest release/ --arch x64",
  },

Then to make a flatpak package I simply do:

npm run build:dist; npm run build:linux; npm run build:flatpak

Essentially electron-builder is used to create an unpacked version of the build (--dir), the files LICENSE and version that @malept/electron-installer-flatpak expects are copied into it, and then @malept/electron-installer-flatpak creates the flatpak (it is fully configurable - check their docs). The contents of electron-version is literally just the electron version number, or in my case 13.6.6.

@vially vially changed the title Add support for building Flatpak bundles Add support for building Flatpak bundles #512 Jun 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants