LibreOffice on Chromebooks

Until recently, Chromebooks could browse the Web and run dedicated ChromeOS and Android applications, and that was that. But things are changing now since Google announced Crostini, a technology to run arbitrary Linux applications on ChromeOS.

What you get, in short, is a Linux distribution running in a virtual machine. It is sandboxed, but with some channels set up between the virtual machine and the surrounding ChromeOS, so that e.g., icons of applications installed in the Linux VM show up in the ChromeOS launcher, and windows opened from within the VM are integrated with the overall ChromeOS desktop.

The default Linux distribution provided by Google is a Debian 9, and one should be able to also plug other flavours of Linux, at least in theory. But we can install applications as flatpaks there, at which point the exact Linux distribution becomes rather irrelevant, anyway.

How to set up your Chromebook to install flapaks is detailed elsewhere, so just follow those instructions. You can then browse flathub for the applications of your choice. But when you click on the “install” button for an app, things start to get a bit rough. The ChromeOS browser downloads a .flatpakref file, but doesn’t know what to do with it, so stores it in the Downloads folder. The Linux VM can’t see it there (thanks to the sandboxing around that VM), so you first need to use the Files app to copy the .flatpakref file from “Downloads” to “Linux files”. The latter is just the home directory of the Linux VM user, so when you switch to the Terminal app (which provides you with a shell for that Linux VM user), you can type flatpak install .flatpakref to finally install the application.

But there is also a more polished solution that doesn’t require falling back to the flatpak command line: Just go back one more time to the Terminal shell to install GNOME Software in the Linux VM, sudo apt install gnome-software gnome-software-plugin-flatpak. Then you can run the Software application from the ChromeOS launcher (it may hide in a “Linux apps” collection). Search for LibreOffice, install it, launch it, and enjoy.

LibreOffice 6 available at

We moved the LibreOffice Flatpak builds to Flathub a while ago, and updating to new versions is normally a pain-free process. (For us as producers of those updates, at least. For you as a user of Flatpak, the process should always be pain-free, anyway.)

However, for LibreOffice 6, building it on Flathub took a bit longer than expected:

Originally, the LibreOffice Flatpak version had lacked a JRE, so some functionality just wasn’t available. There is now a Flatpak extension that allows to bundle Java 9 with an app, so I was finally able to fix this long-standing issue.

In addition, I figured it could be useful to provide debug information for the LibreOffice flatpak (which comes as an extension that you can then optionally install with something like flatpak install flathub org.libreoffice.LibreOffice.Debug).

So I prepared the necessary changes well ahead of the LibreOffice 6.0.0 announcement, tested them locally on my x86_64 machine, and was confident that thinks would just work when I would trigger the Flathub build once the LibreOffice announcement was due. Turned out I was wrong.

First, one little aarch64-specific fix had been missing on the libreoffice-6-0 branch. No problem, just apply the corresponding master fix as a patch to the Flatpak version. Then builds started to fail randomly.

Enabling debug information for an application as large as LibreOffice can increase the size of what gets build, and the time to build it, quite substantially. I do such full-debug-information builds of upstream LibreOffice rather routinely on my (somewhat powerful) local build machine without any problem, so I didn’t even give a thought to this when enabling debug information for the Flathub builds. But it turns out that took some of the Flathub build machines (especially for less powerful platforms, like 32-bit x86) already close to the edge of their capacity. And something as trivial as applying the master-branch patch in the previous step meant that disk-space demand of the LibreOffice builds increased by yet another substantial amount (as Flatpak now needed to install the full LibreOffice git source repository, instead of taking shortcuts). That was apparently enough to move some of the builders over the edge, and into random “disk full” etc. failures.

So I weakened that debug feature again.  There is still unstripped symbol information in the Debug extension that you can download (i.e., you will see meaningful function names in backtraces), just not the whole debug data (e.g., you won’t see source file names and line numbers in backtraces, or be able to print variable values in gdb).

Meanwhile, there had been work going on to finally provide 32-bit arm builds of LibreOffice on Flathub. We had initially disabled that platform because of an issue with the version of GCC 6 that is used to do the builds. That arm-specific issue appears to be fixed with GCC 7, and there is now a Flatpak extension that allows to use GCC 7 instead of 6. And the test branch to do the LibreOffice build with GCC 7 and enable arm worked just fine. When building the old LibreOffice 5.4 version, that is.

When I tried to merge those two efforts that had gone on in parallel, switching to LibreOffice 6 and switching to GCC 7, things started to fail once again.

First off, the Java extension was not available for arm. So building on arm refused to work outright. There is work in progress to make it available, but by now LibreOffice 6 had officially been announced and available for download, and people waiting for the Flatpak version started to get impatient. So I decided to leave 32-bit arm unsupported for just a bit longer and dropped it from the list of supported platforms for the LibreOffice Flathub build again.

But things still didn’t work. The aarch64 build kept failing one of the tests that are executed during the build of LibreOffice. Sometimes these tests are a bit flaky and fail for “random” reasons. So I scheduled multiple builds, just to be sure. But, for sure, aarch64 kept failing, always during the same test.

I had kept using GCC 7 for these builds, even after the original reason for it (to enable 32-bit arm builds) was gone. Looks like there is some issue with building LibreOffice 6.0 with GCC 7, on aarch64 (which I still need to track down in detail). When I switched back to GCC 6, all builds were finally green. And were allowed into the Flathub repo, from where you can install/update them.

(That happened on Friday, just in time to get the LibreOffice 6 Flatpak version battle-tested at FOSDEM. I know at least gicmo’s and my presentations were powered by that version, without a glitch.)

LibreOffice, Flatpak’ed, Flathub’ed


Flathub is the app store for all things Flatpak. And LibreOffice is now available there, too!

When we started flatpak’ing LibreOffice, we made builds of the LibreOffice “Fresh” stream available on the Document Foundation download pages. Since LibreOffice 5.4.2, we now provide such builds through Flathub.

The benefit to you as a user is that there are builds for more architectures (currently aarch64, i386, and x86_64), and that you need to keep track of one less single-app Flatpak repo. (Check out what else is available in the Flathub repo!)

The benefit to me as provider of the original Document Foundation flatpak builds is that the Flathub infrastructure now does those builds for me. We will stop providing the Document Foundation builds after the current LibreOffice 5.4.3.

Too Subtle?

Spot the difference between the two C++ programs

struct S { int a = b, b; };
int main() { return (new S())->a; }


struct S { int a = b, b; };
int main() { return (new S)->a; }

Right, the first one terminates cleanly with exit code zero, while the second one does whatever it deems necessary to counter undefined behavior.

Why is that? The expression new S() means direct-initialization, which for () means value-initialization. Class S has a default constructor that is not user-provided, not deleted, and non-trivial (because non-static data member a has a default member initializer). So the instance of S is first zero-initialized, then default-initialized. Zero-initialization means that a and b are initialized to zero. Default-initialization for S means that the default constructor is called, which means that a is initialized from its default member initializer, by copying zero from b (and then b is default-initialized, leaving it alone).

On the other hand, just new S (without the parentheses) means just default-initialization (without previous zero-initialization). So, again, default-initialization for S means that the default constructor is called, which means that a is initialized from its default member initializer, copying the uninitialized b (and then b is default-initialized, leaving it uninitialized)…

Too subtle? Probably.

LibreOffice.flatpak update

New revisions of LibreOffice are routinely uploaded to by now. But things have changed slightly with the recent upload of LibreOffice 5.2.3:

GNOME Software (at least the version available in Fedora 25 beta) can now handle .flatpak files, so throwing the downloaded LibreOffice.flatpak at it will allow you to install the flatpak onto your system without resorting to the command line. (Just remember, for now, to first install the GNOME 3.20 runtime as detailed at, or GNOME Software might refuse to install the LibreOffice.flatpak with an odd error message like “Could not find ‘org.libreoffice.LibreOffice.destkop’”.)

But for that to work the LibreOffice.flatpak had to be stripped down to advertise just a single application (a single org.libreoffice.LibreOffice.appdata.xml and a single org.libreoffice.LibreOffice.desktop). So when you have installed the flatpak, you’ll now only see a single application icon (the “generic” document icon) instead of the various sub-application icons for Writer, Calc, Impress, etc. (The upside being that you’ll thus no longer confuse your Linux distro’s LibreOffice installation with the flatpak one.) And opening new Writer, Calc, Impress, etc. documents still works from the “generic” application icon’s context menu.

Another recent improvement is that flatpak’s xdg-desktop-portal (and GNOME-specific xdg-desktop-portal-gtk backend) is now available (again, at least in Fedora 25 beta), so that clicking on hyperlinks in LibreOffice documents (or requesting the LibreOffice online help, e.g. by pressing F1) will now forward those requests to your browser and open the links there.

Clang in Fedora 24

I’m only ever using a bleeding edge Clang trunk build myself. So when Fedora enabled use of the GCC abi_tag attribute in libstdc++ (i.e., switched the _GLIBCXX_USE_CXX11_ABI macro to 1 by default), it was only a matter of applying a set of (evolving) patches to Clang to keep things working.

However, others who wanted to use the Clang version included in Fedora were in for more of a problem. The typical symptom being that what you compiled with Clang fails to link against system libraries, most notably libstdc++.

For Fedora 23, we included a somewhat slapdash early version of the relevant Clang patches, but that didn’t survive the split-out of Clang from the overall LLVM package in Fedora 24. But now that the Clang upstream patches are deemed stable (and have been integrated into trunk towards Clang 3.9), I backported them to the Clang 3.8 in Fedora 24 (and rawhide).

And a lot of thanks to all of those who created these patches!

Plugin, Flamed

Just how much is our Clang plugin slowing down builds of LibreOffice? We are constantly adding more and more useful functionality to it, and some of it is well known to be written in a way that is likely performing not too well. But I never dared look at the performance implications too closely, for fear of being disappointed. The build always seemed to go along at more or less the same speed, so who cares for details?

Enter FlameGraph, generating beautiful and easy-to-digest graphs on top of the Linux perf tool’s (or others’) output. So I gathered data about half a minute of CPU activity during the LibreOffice build (randomly picked a time when all the cores were busy compiling .cxx files in the sw module, to keep noise contributed by other processes down to a minimum), and passed it through FlameGraph. And sobering set in:flamegraph98.56% of all the time was spent in the clang-3.9 process (i.e., there was almost no noise from unrelated processes). And 19.22% of all time was spent in our plugin. That is, the plugin slows down compilation by about 25%. Quite a number.

Zooming in and breaking this down further per individual plugin, the distribution is

  • 1.47% CommaOperator
  • 1.04% VCLWidgets
  • 0.91% BodyNotInBlock
  • 0.79% SalBool
  • 0.69% PtrVector
  • 0.65% RefCounting
  • 0.63% FailedDynCast
  • 0.62% ReservedId
  • 0.61% Nullptr
  • 0.59% RedundantCast
  • 0.56% StringConstant
  • 0.56% ImplicitBoolConversion
  • 0.55% ExternAndNotDefined
  • 0.50% PassStuffByRef
  • 0.47% DefaultParams
  • 0.46% StringConcat
  • 0.45% UnusedVariableCheck
  • 0.45% SalLogAreas
  • 0.45% LiteralToBoolConversion
  • 0.44% UnrefFun
  • 0.44% ReturnByRef
  • 0.43% StaticCall
  • 0.43% BadStatics
  • 0.42% Override
  • 0.41% StaticAnonymous
  • 0.41% InlineVisible
  • 0.38% SimplifyBool
  • 0.38% FpComparison
  • 0.37% SfxPoolItem
  • 0.35% StaticMethods
  • 0.35% PrivateBase
  • 0.35% BadVectorInit
  • 0.34% DerefNullPtr
  • 0.34% CStyleCast
  • 0.32% RangeForCopy
  • 0.32% LoopVarTooSmall
  • 0.29% OnceVar

The recursive nature of RecursiveASTVisitor makes it a bit hard to easily spot each individual plugin’s hotspots, but one thing sticks out: CommaOperator is a rather simple piece of code (that shouldn’t need much heavy computation), but does use lopluign::Pluign::parentStmt, which rebuilds the AST to determine a node’s parent, and is really, really expensive.

Room for improvement. Time to clean up.

(At first, the generated graph looked way less interesting. One thing that was necessary was to build both LLVM/Clang and our plugin with -fno-omit-frame-pointer. The other thing was to teach FlameGraph to support “(anonymous namespace)” in C++ function names.)