February updates

Our February update is here, with some great new features and usability improvements.

Conveyor can now distribute Flutter apps, draw icons for you if you don’t have them already, do in-JAR code signing to make using native libraries easier for JVM apps, use EV certificates stored in YubiKeys, bundle the Microsoft VC++ redistributables, and catches many common errors.


Flutter is Google’s open source toolkit for writing apps that target Android and iOS. We keep hearing good things about Flutter from happy developers, and since they added support for desktop apps last year it made sense to make it work well with Conveyor. Thanks to the Dart language and a high performance C++ runtime Flutter apps look and feel great for the end user, whilst also supporting developer-friendly features like hot reload.

Keep an eye out for a dedicated blog post on this feature soon, but for now take a look at our repo showing how to package the Flutter hello world using GitHub Actions to compile for each supported platform, and look at the documentation.

Icon generation

Conveyor will now draw icons for you if you don’t supply any. It also learned to render SVG files whilst framing them in a macOS-styled rounded rectangle, and it’ll now resample any image icons to the right sizes if you don’t have every icons in every needed dimension.

An example of a synthetic icon

Here’s an example that’s generated for the Flutter Demo app above. You can change the letters and gradient used if you don’t like the default choices. This makes it much more convenient to package quick prototypes, internal tools, CLI apps and student projects where you aren’t ready to get some beautiful art assets yet.

A future blog post will show how to control this feature and go into the reasons we implemented it.

In-JAR code signing for JVM apps

JVM libraries often distribute native code inside JARs and extract them on the fly. With other tools this fact causes immense problems with code signing, because the code inside the JARs doesn’t get signed.

Previously Conveyor extracted the right libraries for each target OS, signed them and placed them in the JVM’s lib directory. It can still do this, but now you also have the option of having native libraries be signed in place inside the JARs. This mode is the new default when conveyor.compatibility-level >= 7 and drastically simplifies the packaging process by improving compatibility with existing apps. This does come at a cost in download size, startup time and pollution of the user’s home directory so turning on library extraction is still recommended, but it’s no longer mandatory. To get back the old behavior set app.jvm.extract-native-libraries = true and make sure to configure any needed system properties.

With this improvement JavaCV is now usable out of the box, opening up the world of JVM computer vision apps.

An upcoming blog post will describe this feature in more detail.

YubiKey support

A YubiKey HSM device

If you’re launching a Windows app for the first time it can help to have an Extended Validation certificate. This lets you sign new code whilst benefiting from some pre-purchased reputation with SmartScreen, meaning Windows won’t warn the user that the app is rarely downloaded.

EV certificates must be stored in hardware security modules. Conveyor supports this, and now has additional support for the YubiKeys as used by ssl.com and other CAs. These USB HSMs required a bit of extra logic because they come with multiple private keys inside and the right one must be selected. You can now also specify the specific key alias you need, if you’re using a custom HSM that manages many keys and certificates.

Microsoft Visual C++ redistributables

Windows apps often require the Microsoft Visual C++ runtime DLLs (msvcp140.dll, vcruntime140.dll etc). These don’t come with Windows and most toolchains won’t bundle them with your app either, meaning you’re expected to do it at packaging time. This is especially annoying because Microsoft only distribute these DLLs in the form of installer EXEs. Conveyor now makes it easy to include all these DLLs or just the specific libraries your app needs.

To bundle the VC runtime, write:

include required("/stdlib/windows/msvc.conf")

msvc.input.remap = [
  # Name the DLLs you need here:
  # And drop the rest.

If you don’t specify msvc.input.remap then all the DLLs will be included. This should always be safe but can bloat your package. The following files are available:

  • msvcp140.dll
  • msvcp140_1.dll
  • msvcp140_2.dll
  • msvcp140_atomic_wait.dll
  • msvcp140_codecvt_ids.dll
  • vcamp140.dll
  • vccorlib140.dll
  • vcomp140.dll
  • vcruntime140.dll
  • vcruntime140_1.dll

The msvc.conf stdlib file looks like this:

msvc.version = 14.0.30704.0
msvc.redist-url = "https://downloads.hydraulic.dev/msvc-redist/msvc-redist-"${msvc.version}".zip"
msvc.input = { from = ${msvc.redist-url} }
app.windows.amd64.inputs += ${msvc.input}

Microsoft don’t distribute these DLLs in zip form. We extract the DLLs from their VC++ runtime packages and host them for you, so you can include only what you need. Normally your app framework will tell you what DLLs are required but if you don’t know or are writing a native app you can use Dependency Walker to find out. Our hosted redistributables include the DLLs at version 14.0.30704.0, and we’ll update them from time to time.

Usability improvements

We make a big effort to make app distribution easy, but despite that there are still a few ways things can go wrong. When users to come to us for support we look for ways to detect that mistake and add it to the product. Conveyor can now detect and warn you about these errors:

  • Copy/pasting a line like app.foo.bar = baz inside an app {} block will accidentally define a key named app.app.foo.bar. This mistake is now detected.
  • If you copy/paste the sample config from our documentation without reading it, you might end up trying to use https://downloads.myproject.org/some/path as your base URL. Conveyor now detects this and warns you about it.
  • Overwriting an existing released version with different packages. This can cause issues with almost any update system but will especially cause problems on old versions of Windows. This check can be overridden if you’re sure you know what you’re doing.
  • Accidentally changing your signing identity. This can happen if you switch Windows signing certificates without noticing that they’re not issued to the same subject name e.g. if your company rebrands, or if you switch between OV and EV certificates.
  • For JVM apps Conveyor now also checks that you’re not using old versions of JavaFX that may fail to start on Windows when used in combination with some JDKs.

You can now use any type of localhost domain in your site URL when testing, as specified by RFC 2606 and RFC 6762. This includes .local domains, so you can easily host a demo server using multicast DNS.

Support for serving off S3

We now support serving update sites from any S3 compatible service.

Previously Conveyor used a “flat” update site layout, in which all packages and update metadata files are in the same directory. This was done both for simplicity and to be compatible with GitHub Releases. For this to work on Debian based distributions requires that the server hosting the update site be a normal web server that interprets URLs as file paths. Amazon S3 and similar services don’t meet this requirement because they interpret URLs as keys into a key/value store. To fix this Conveyor now builds a non-flat layout in which the generated apt repository uses nested directories, unless your project is hosted on GitHub Releases or has previously done releases using the flat layout.

Other enhancements

There are many other small enhancements and bugfixes - see the release notes for details.