| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 1 | Cross-compiling LibreOffice |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 2 | *************************** |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 3 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 4 | Cross-compilation works, to various degree, to the following |
| Tor Lillqvist | 6dd7798 | 2015-12-17 21:22:45 +0200 | [diff] [blame] | 5 | platforms: iOS, Android, and Raspbian. |
| 6 | |
| 7 | Note that this document has not been updated very often, and not |
| 8 | everything here necessarily is true any more. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 9 | |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 10 | |
| 11 | General |
| 12 | ------- |
| 13 | |
| 14 | In GNU Autoconf terminology, "build" is the platform on which you are |
| Tor Lillqvist | bc229ca | 2012-05-17 22:57:46 +0300 | [diff] [blame] | 15 | running a build of some software and "host" is the platform on which |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 16 | the software you are building will run. Only in the specific case of |
| 17 | building compilers and other programming tools is the term "target" |
| 18 | used to indicate the platform for which the tools your are building |
| 19 | will produce code. As LibreOffice is not a compiler, the "target" term |
| 20 | should not be used in the context of cross-compilation. |
| 21 | |
| 22 | (For a case where all three of "build", "host" and "target" are |
| 23 | different: consider a gcc cross-compiler running on Windows, producing |
| 24 | code for Android, where the cross-compiler itself was built on |
| 25 | Linux. (This is a real case.) An interesting tidbit is that such |
| 26 | configurations are called "Canadian Cross".) |
| 27 | |
| 28 | Even though the LibreOffice build mechanism is highly unorthodox, the |
| 29 | configure script takes the normal --build and --host options like any |
| 30 | GNU Autoconf -based configure script. To cross-compile, you basically |
| 31 | need just to specify a suitable --host option and things should work |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 32 | out nicely. In practice, many details need to be handled. See examples |
| 33 | below. |
| 34 | |
| 35 | Note that in the case of LibreOffice, it is uncommon to run the |
| 36 | configure script directly. Normally one uses the autogen.sh script. |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 37 | The autogen.sh script reads command-line options from file called |
| Chris Sherlock | 91b27bc | 2013-05-16 00:49:50 +1000 | [diff] [blame] | 38 | autogen.input if it exists. The typical way of working is to keep |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 39 | the configure parameters in that file and edit it as needed. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 40 | |
| 41 | |
| 42 | What is so hard, then? |
| 43 | ---------------------- |
| 44 | |
| 45 | Despite the fact that the configure script takes normal --build and |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 46 | --host options, that is just the beginning. It was necessary to |
| 47 | separate tests for "host" and "build" platforms in the configure |
| 48 | script. See the git log for details. And the reasonably "standard" |
| 49 | configure.in is just the top level; when we get down to the actual |
| 50 | makefilery used to build the bits of LibreOffice, it gets much worse. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 51 | |
| 52 | |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 53 | iOS |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 54 | *** |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 55 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 56 | iOS is the operating system on Apple's mobile devices. Clearly for a |
| 57 | device like the iPad it would not be acceptable to run a normal |
| 58 | LibreOffice application with overlapping windows and mouse-oriented |
| 59 | GUI widgets. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 60 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 61 | It makes sense to use only a part of LibreOffice's code for iOS. Lots |
| 62 | of the GUI-oriented code should be left out. iOS apps that want to use |
| 63 | the applicable LibreOffice code will handle all their GUI in a |
| 64 | platform-dependent manner. How well it will be possible to do such a |
| 65 | split remains to be seen. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 66 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 67 | Obviously we want it to be possible to eventually distribute apps |
| 68 | using LibreOffice code through the App Store. Technically, one |
| 69 | important special aspect of iOS is that apps in the App Store are not |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 70 | allowed to load own dynamic libraries. (System libraries are used in |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 71 | the form of dynamic libraries, just like on Mac OS X, of which iOS is |
| 72 | a variant.) |
| 73 | |
| 74 | Thus all the libraries in LibreOffice that normally are shared |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 75 | libraries (DLLs on Windows, shared objects (.so) on Linux, dynamic |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 76 | libraries on Mac OS X (.dylib)) must be built as static archives |
| 77 | instead. This has some interesting consequences for how UNO is |
| 78 | implemented and used. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 79 | |
| Andrea Gelmini | 64a3124 | 2017-08-17 16:41:20 +0200 | [diff] [blame] | 80 | An iOS app is a "bundle" that contains a single executable. In an app |
| 81 | using LibreOffice code, that executable then contains the necessary |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 82 | LibreOffice libraries and UNO components statically linked. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 83 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 84 | The Apple tool-chain for iOS cross-building is available only for OS |
| 85 | X. In order to be able to run and debug an app on an actual device |
| 86 | (and not just the iOS Simulator) you need to be registered in the iOS |
| 87 | Developer Program. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 88 | |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 89 | Here is an autogen.input for iOS (device) using Xcode 4.6, on OS X 10.8: |
| Tor Lillqvist | bc229ca | 2012-05-17 22:57:46 +0300 | [diff] [blame] | 90 | |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 91 | --build=i386-apple-darwin10.7.0 |
| 92 | --host=arm-apple-darwin10 |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 93 | --enable-dbgutil |
| 94 | --enable-debug |
| Tor Lillqvist | 21aec7e | 2012-02-22 20:41:58 +0200 | [diff] [blame] | 95 | --enable-werror |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 96 | |
| Tor Lillqvist | f285ac7 | 2014-07-09 12:21:53 +0300 | [diff] [blame] | 97 | For the iOS Simulator, but note that building for the simulator is |
| 98 | broken at the moment (July 2014): |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 99 | |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 100 | --build=i386-apple-darwin10.7.0 |
| 101 | --host=arm-apple-darwin10 |
| 102 | --enable-ios-simulator |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 103 | --enable-dbgutil |
| 104 | --enable-debug |
| 105 | --enable-werror |
| Tor Lillqvist | 21aec7e | 2012-02-22 20:41:58 +0200 | [diff] [blame] | 106 | |
| Tor Lillqvist | f285ac7 | 2014-07-09 12:21:53 +0300 | [diff] [blame] | 107 | You will have to install autoconf and automake yourself before running |
| 108 | autogen.sh. They are no longer included in Xcode 4.3 and later (not |
| 109 | even in the add-on "command line tools"). |
| Tor Lillqvist | 21aec7e | 2012-02-22 20:41:58 +0200 | [diff] [blame] | 110 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 111 | The -mmacosx-version-min=10.7 is necessary when building for the iOS |
| Tor Lillqvist | ab4014e | 2012-06-04 11:19:36 +0300 | [diff] [blame] | 112 | simulator to avoid clang replacing simple calls to fprintf with calls |
| 113 | to fwrite$UNIX2003 which Xcode then warns that doesn't exist on iOS. |
| 114 | |
| Tor Lillqvist | 21aec7e | 2012-02-22 20:41:58 +0200 | [diff] [blame] | 115 | |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 116 | Android |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 117 | ******* |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 118 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 119 | From a technical point of view the core Android OS (the kernel) is |
| 120 | Linux, but everything else is different. Unlike iOS, an Android app |
| 121 | can use shared objects just fine, so that aspect of UNO doesn't need |
| 122 | special handling. Except that there is a silly low limit in the |
| 123 | Android dynamic linker on the number of libraries you can dlopen. This |
| 124 | is a limitation in user-level (but system-provided and not really |
| 125 | replaceable) code, not the kernel. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 126 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 127 | Thus, just like for iOS, also for Android the LibreOffice libraries |
| 128 | and UNO components are built as static archives. For Android, those |
| 129 | static archives, and any app-specific native code, are linked into one |
| 130 | single app-specific shared library, called liblo-native-code.so. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 131 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 132 | For the GUI, the same holds as said above for iOS. The GUI layer needs |
| 133 | to be platform-specific, written in Java. |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 134 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 135 | Android cross-compilation work has been done mainly on Linux (openSUSE |
| 136 | in particular). Earlier also cross-compiling from OS X was tried. The |
| 137 | Android cross-compilation tool-chain (the "Native Development Kit", or |
| 138 | NDK) is available for Linux, OS X and Windows, but trying to |
| 139 | cross-compile LibreOffice from Windows will probably drive you insane. |
| Tor Lillqvist | 0f9f8ef | 2012-09-10 14:28:34 +0300 | [diff] [blame] | 140 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 141 | You will also need the Android SDK as full "make" also builds a couple |
| 142 | of Android apps where the upper layer is written in Java. |
| Tor Lillqvist | 199d220 | 2012-01-03 13:01:47 +0200 | [diff] [blame] | 143 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 144 | Use the "android" tool from the SDK to install the SDK Tools, SDK |
| Jan Holesovsky | c79e70f | 2014-06-26 10:57:05 +0200 | [diff] [blame] | 145 | Platform Tools, the API 15 SDK Platform and the Android Support |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 146 | Library. If you want to run the Android apps in the emulator, you of |
| 147 | course need an appropriate system image for that. |
| 148 | |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 149 | Here is an autogen.input for Android on ARM when cross-compiling |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 150 | from Linux: |
| 151 | |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 152 | --enable-dbgutil |
| Tor Lillqvist | ab236e1 | 2012-08-09 12:59:08 +0300 | [diff] [blame] | 153 | --enable-werror |
| Michael Meeks | e61e51a | 2012-08-03 16:39:20 +0100 | [diff] [blame] | 154 | --with-distro=LibreOfficeAndroid |
| Tor Lillqvist | 9a6beed | 2011-12-15 23:54:31 +0200 | [diff] [blame] | 155 | |
| Tor Lillqvist | 2462aa6 | 2014-02-21 22:37:47 +0200 | [diff] [blame] | 156 | And here is an (quite old) autogen.input for Android on X86: |
| Michael Meeks | e61e51a | 2012-08-03 16:39:20 +0100 | [diff] [blame] | 157 | |
| Michael Meeks | e61e51a | 2012-08-03 16:39:20 +0100 | [diff] [blame] | 158 | --with-android-ndk=/opt/libreoffice/android-ndk-r8b |
| 159 | --with-android-ndk-toolchain-version=4.6 |
| 160 | --with-android-sdk=/opt/libreoffice/android-sdk-linux |
| 161 | --build=i586-suse-linux |
| 162 | --enable-ccache |
| Michael Meeks | e61e51a | 2012-08-03 16:39:20 +0100 | [diff] [blame] | 163 | --with-distro=LibreOfficeAndroidX86 |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 164 | |
| Tor Lillqvist | 1b53066 | 2015-05-21 16:54:28 +0100 | [diff] [blame] | 165 | A LibreOffice app for Android is being developed progress in the |
| Miklos Vajna | 562d8f5 | 2015-05-21 17:55:28 +0100 | [diff] [blame] | 166 | android/source directory. |
| Tor Lillqvist | 3ef7293 | 2012-01-03 13:48:29 +0200 | [diff] [blame] | 167 | |
| Tor Lillqvist | 1b53066 | 2015-05-21 16:54:28 +0100 | [diff] [blame] | 168 | To run the app, do "make install" followed by either "make run" or |
| Miklos Vajna | b0cb454 | 2015-03-19 16:16:55 +0100 | [diff] [blame] | 169 | starting it from Android itself. You most likely want to have an "adb logcat" |
| 170 | running in another window. To debug, run "make debugrun". |
| Jan Holesovsky | c862be0 | 2014-10-13 16:51:08 +0200 | [diff] [blame] | 171 | |
| Jan Holesovsky | cfd74ae | 2014-06-27 15:44:25 +0200 | [diff] [blame] | 172 | NB: If you happen to upgrade to Android SDK Tools 23, and the build (using |
| 173 | 'make verbose=t android') fails for you with: |
| 174 | |
| 175 | [dx] UNEXPECTED TOP-LEVEL EXCEPTION: |
| Andrea Gelmini | da40cac | 2014-11-10 15:05:25 +0100 | [diff] [blame] | 176 | [dx] java.io.FileNotFoundException: /local/libreoffice/android-sdk-linux/tools/support/annotations.jar (no such file or directory) |
| Jan Holesovsky | cfd74ae | 2014-06-27 15:44:25 +0200 | [diff] [blame] | 177 | |
| 178 | you need to copy the annotations.jar from an older sdk; like |
| 179 | |
| 180 | wget 'http://dl-ssl.google.com/android/repository/tools_r22.6.2-linux.zip' |
| 181 | unzip tools_r22.6.2-linux.zip |
| 182 | cp tools/support/annotations.jar <android-sdk-linux>/tools/support/ |
| Tor Lillqvist | ad4a467 | 2011-05-27 18:29:43 +0300 | [diff] [blame] | 183 | |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 184 | Raspbian |
| Tor Lillqvist | 30fded6 | 2013-03-18 09:24:41 +0200 | [diff] [blame] | 185 | ******** |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 186 | |
| Matúš Kukan | ee2d727 | 2014-01-16 15:56:30 +0100 | [diff] [blame] | 187 | In theory, this should work also for another Linux, it does not need to be Raspbian. |
| Tor Lillqvist | 661ab31 | 2014-02-22 13:48:40 +0200 | [diff] [blame] | 188 | But this cross-compilation work is tested from Debian and openSUSE to Raspbian. |
| Matúš Kukan | ee2d727 | 2014-01-16 15:56:30 +0100 | [diff] [blame] | 189 | |
| Tor Lillqvist | 78a6158 | 2014-01-20 15:01:25 +0200 | [diff] [blame] | 190 | You will need headers, pkg-config files and libraries from a Raspbian |
| 191 | system to build against. Available at |
| Paul Menzel | e8918c4 | 2017-05-17 11:55:46 +0200 | [diff] [blame] | 192 | https://dev-www.libreoffice.org/extern/ . Look for the latest |
| Tor Lillqvist | 78a6158 | 2014-01-20 15:01:25 +0200 | [diff] [blame] | 193 | raspbian-root-*.tar.gz . For instance: |
| 194 | |
| Paul Menzel | e8918c4 | 2017-05-17 11:55:46 +0200 | [diff] [blame] | 195 | $ wget https://dev-www.libreoffice.org/extern/raspbian-root-20140120.tar.gz |
| Tor Lillqvist | 78a6158 | 2014-01-20 15:01:25 +0200 | [diff] [blame] | 196 | $ mkdir raspbian-root |
| 197 | $ cd raspbian-root |
| 198 | $ tar -xf raspbian-root-20140120.tar.gz |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 199 | |
| 200 | You can build cross-compiler yourself or get the executables here: |
| 201 | $ git clone git://github.com/raspberrypi/tools |
| Tor Lillqvist | 78a6158 | 2014-01-20 15:01:25 +0200 | [diff] [blame] | 202 | |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 203 | tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian is known to work. |
| 204 | |
| 205 | Then create pkg-config wrapper, something like: |
| 206 | $ cat > pkg-config-wrapper-host << _EOF |
| 207 | #!/bin/sh |
| 208 | |
| Michael Stahl | d729d16 | 2014-02-27 16:19:43 +0100 | [diff] [blame] | 209 | if [ "$CROSS_COMPILING" = TRUE ]; then |
| Tor Lillqvist | 78a6158 | 2014-01-20 15:01:25 +0200 | [diff] [blame] | 210 | SYSROOT=$HOME/lo/raspbian-root |
| 211 | export PKG_CONFIG_PATH=${SYSROOT}/usr/lib/arm-linux-gnueabihf/pkgconfig:${SYSROOT}/usr/share/pkgconfig |
| 212 | export PKG_CONFIG_LIBDIR=${SYSROOT}/usr/lib/pkgconfig |
| 213 | export PKG_CONFIG_SYSROOT_DIR=${SYSROOT} |
| 214 | fi |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 215 | |
| 216 | exec pkg-config "\$@" |
| 217 | _EOF |
| 218 | $ chmod +x pkg-config-wrapper-host |
| Tor Lillqvist | 78a6158 | 2014-01-20 15:01:25 +0200 | [diff] [blame] | 219 | |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 220 | This does not work with pkg-config 0.23. 0.26 is known to work. |
| 221 | |
| Tor Lillqvist | 5011f4c | 2013-05-01 20:47:02 +0300 | [diff] [blame] | 222 | And you are ready to build with autogen.input similar to: |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 223 | |
| 224 | PKG_CONFIG=<path-to-pkg-config-wrapper-host> |
| 225 | CC=<path-to-arm-linux-gnueabihf-gcc> --sysroot=<path-to-raspbian_rootfs> |
| 226 | CXX=<path-to-arm-linux-gnueabihf-g++> --sysroot=<path-to-raspbian_rootfs> |
| 227 | --build=x86_64-unknown-linux-gnu |
| 228 | --host=arm-unknown-linux-gnueabihf |
| Matúš Kukan | ee2d727 | 2014-01-16 15:56:30 +0100 | [diff] [blame] | 229 | --disable-sdk |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 230 | --enable-python=system |
| 231 | PYTHON_CFLAGS=-I<path-to-raspbian_rootfs>/usr/include/python2.7 |
| 232 | PYTHON_LIBS=-lpython2.7 |
| 233 | --with-java |
| 234 | JAVAINC=-I<path-to-raspbian_rootfs>/usr/lib/jvm/java-6-openjdk-armhf/include |
| Matúš Kukan | 63a1321 | 2013-03-14 17:05:15 +0100 | [diff] [blame] | 235 | --with-system-cairo |
| 236 | --with-system-cppunit |
| 237 | --with-system-icu |
| 238 | --with-system-neon |
| 239 | --with-system-nss |
| 240 | --with-system-openldap |
| 241 | --with-system-openssl |
| 242 | --with-system-redland |
| 243 | |
| 244 | Finally, when you are ready to run the binaries in Raspbian, |
| Matúš Kukan | ee2d727 | 2014-01-16 15:56:30 +0100 | [diff] [blame] | 245 | you may need to get more system libraries, who knows. |
| 246 | $ sudo apt-get install libreoffice # or similar |
| 247 | That installs libreoffice too, which you don't need because you have |
| 248 | just built one, but I don't know how to avoid it easily. |