These builds are done on an x86_64 machine for the RPi3 running Slackware arm-current [armv7_hf] or Slarm64 [aarch64][history][download from a Slackware mirror - for example slackware.uk where rsync is available].
Although this page is primarily about cross compiling LibreOffice for the RPi3, that setup is an addition to a native x86_64 build, and so cross compiling is shown as an addition to the native build. An i686 cross build option is included as it's an identical setup to the arm cross builds.
There are therefore four build options - native x86_64; cross armv7, aarch64, or i686.
The page has been laid out so that the contents can be copied and pasted into a console allowing a step-by-step build to aid troubleshooting.
LO build environment
/LO_build
├── libreoffice-x.x.x.x build from source tarballs
├── external_tarballs source archives for non-system build requirements
├── pkg-$Arch DESTDIR for packaging installation
└── LO-$Arch-sysroot installation directory for HOST libs and headers
With the exception of these initial downloads, the non-system sources will be downloaded during 'make'.
cd /LO_build/
export LO_VERSION=6.3.3.2
Build from tarballs
download
(cd external_tarballs
SRC_URL=https://download.documentfoundation.org/libreoffice/src
DIR=$(echo $LO_VERSION | cut -d "." -f1-3)
wget $SRC_URL/$DIR/libreoffice-$LO_VERSION.tar.xz
wget $SRC_URL/$DIR/libreoffice-dictionaries-$LO_VERSION.tar.xz
wget $SRC_URL/$DIR/libreoffice-help-$LO_VERSION.tar.xz
wget $SRC_URL/$DIR/libreoffice-translations-$LO_VERSION.tar.xz)
extract
tar xf external_tarballs/libreoffice-$LO_VERSION.tar.xz
## uncompress any of the submodule tarballs now if they need patching - for example:
tar xf external_tarballs/libreoffice-translations-$LO_VERSION.tar.xz
## apply patch
(cd libreoffice-$LO_VERSION/translations/source/en-GB/helpcontent2/source/text/scalc/
line_no=$(grep -n "msgstr.*COLOR function" 01.po | cut -d: -f1)
sed -i "${line_no}s|COLOR|COLOUR|" 01.po)
## let the build know that the submodule has been unpacked …
mkdir -p libreoffice-$LO_VERSION/src/libreoffice-translations-$LO_VERSION
cd libreoffice-$LO_VERSION
Native build - variables will be overwritten if cross compiling
Set the configure option --host == --build [using the autotools definition of host - the machine the compiled code will run on]
export HOST=$(bash ./config.guess)
export Arch=x86_64
export STRIP=strip
Gcc optimization
## for build machine, for native x86_64 or cross i686 builds, for LO to run on same machine architecture
export OPTM=$(echo $(gcc -Q -O2 -march=native --help=target | grep -E "^ -march=|^ -mtune=|^ -mfpmath=" | tr -d [:blank:]))
## or set manually for the intended x86 host machine
## export OPTM=
export CC="gcc ${OPTM:-}"
export CXX="g++ ${OPTM:-}"
Cross compiling setting up for cross compiling
/opt
└── cross-pi-gcc cross tools
└── sysroot location defined in x-tools build
Set the cross tools directories
export XGCC_DIR=/opt/cross-pi-gcc
export SYSROOT=$XGCC_DIR/sysroot
[1] Set variables for an armv7, aarch64, or i686 build.
32-bit armv7_hf
export HOST=arm-linux-gnueabihf
export Arch=armv7
export STRIP=$HOST-strip
## the cross compiler has been built with arm_hf optimizations
export CC=$HOST-gcc
export CXX=$HOST-g++
export LIBDIRSUFFIX=""
## Slack_base = where the Slackware packages a-y directories are
export Slack_base=/path_to_Slackware_arm_current
Error:
/LO_build/libreoffice-6.3.3.2/sal/osl/unx/process_impl.cxx:108:14: error: ‘PATH_MAX’ was not declared in this scope
… and others …
Add linux/limits.h which defines PATH_MAX:
sed -i 's|limits.h>|&\n#include <linux/limits.h>|' {sal/osl/unx/process_impl.cxx,cppuhelper/source/findsofficepath.c,desktop/unx/source/start.c,vcl/unx/generic/fontmanager/helper.cxx,uui/source/logindlg.cxx}
sed -i 's|MSVC|&\n#include <linux/limits.h>|' pyuno/source/loader/pyuno_loader.cxx
OR:
64-bit aarch64
export HOST=aarch64-linux-gnu
export Arch=aarch64
export STRIP=$HOST-strip
## -march=armv8-a+crc is the default compiler optimization, so just add -mtune=cortex-a53
export CC="$HOST-gcc -mtune=cortex-a53"
export CXX="$HOST-g++ -mtune=cortex-a53"
export LIBDIRSUFFIX=64
## Slack_base = where the Slarm64 packages a-y directories are
export Slack_base=/path_to_Slarm64
OR:
32-bit x86 - i686
export HOST=i686-linux-gnu
export Arch=i686
export STRIP=$HOST-strip
export CC="$HOST-gcc ${OPTM:-}"
export CXX="$HOST-g++ ${OPTM:-}"
export LIBDIRSUFFIX=""
## build can't find 'libssp.so.0', which Slackware doesn't include
export LD_LIBRARY_PATH=$XGCC_DIR/$HOST/lib
## Slack_base = where the Slackware packages a-y directories are
export Slack_base=/path_to_Slackware32_current
[2] Cross compiler
Install cross tools
installpkg /tmp/xgcc910-glibc2.29-<for_Arch>.txz
To avoid any issues with the different limits.h priorities producing this error:
.../include/bits/stdlib.h:90:3: error: #error "Assumed value of MB_LEN_MAX wrong"
use the work-around as detailed here.
(cd $XGCC_DIR/lib/gcc/*-linux-gnu*/9.1.0/plugin/include/
cat limitx.h glimits.h limity.h > ../../include-fixed/limits.h)
Location of installed HOST libs and headers
export HOST_INSTN=/LO_build/LO-$Arch-sysroot
[3] Set up a sysroot for the HOST libs and headers needed for the LibreOffice build.
OR skip this and just mount the media containing the HOST installation to $SYSROOT
My preference is to set this up in a separate directory and bind-mount it to the cross compiler sysroot directory.
This enables me to set up different sysroots for whatever is being cross compiled.
Install kernel headers and Slackware or Slarm64 libs/headers to a HOST_installation directory
export ROOT=$HOST_INSTN
installpkg /tmp/kernel-headers-<for_Arch>.txz
cd $Slack_base
installpkg a/bzip2-*.txz
installpkg a/dbus-*.txz
installpkg a/util-linux-*.txz
installpkg a/xz-*.txz
installpkg ap/cups-*.txz
installpkg ap/sqlite-*.txz
installpkg d/gcc-9.1.0-*.txz
installpkg d/gcc-g++-9.1.0-*.txz
installpkg d/python-2.*.txz
installpkg d/python3-*.txz
installpkg l/at-spi2-atk-*.txz
installpkg l/at-spi2-core-*.txz
installpkg l/atk-*.txz
installpkg l/cairo-*.txz
installpkg l/expat-*.txz
installpkg l/freetype-*.txz
installpkg l/fribidi-*.txz
installpkg l/gdk-pixbuf2-*.txz
installpkg l/glib2-*.txz
installpkg l/gmp-*.txz
installpkg l/graphite2-*.txz
installpkg l/gtk+2-*.txz
installpkg l/gtk+3-*.txz
installpkg l/harfbuzz-*.txz
installpkg l/icu4c-*.txz
installpkg l/libffi-*.txz
installpkg l/libidn2-*.txz
installpkg l/libpng-1.6.*.txz
installpkg l/libunistring-0.9.*.txz
installpkg l/libxml2-*.txz
installpkg l/libxslt-*.txz
installpkg l/mozilla-nss-*.txz
installpkg l/pango-*.txz
installpkg l/pcre-*.txz
installpkg l/shared-mime-info-*.txz
installpkg l/zlib-*.txz
installpkg n/gnutls-*.txz
installpkg n/nettle-*.txz
installpkg n/p11-kit-*.txz
installpkg x/fontconfig-*.txz
installpkg x/libICE-*.txz
installpkg x/libSM-*.txz
installpkg x/libX11-*.txz
installpkg x/libXau-*.txz
installpkg x/libXcomposite-*.txz
installpkg x/libXcursor-*.txz
installpkg x/libXdamage-*.txz
installpkg x/libXdmcp-*.txz
installpkg x/libXext-*.txz
installpkg x/libXfixes-*.txz
installpkg x/libXi-*.txz
installpkg x/libXinerama-*.txz
installpkg x/libXrandr-*.txz
installpkg x/libXrender-*.txz
installpkg x/libXtst-*.txz
installpkg x/libXxf86vm-*.txz
installpkg x/libdrm-*.txz
installpkg x/libepoxy-*.txz
installpkg x/libglvnd-*.txz
installpkg x/libpthread-stubs-*.txz
installpkg x/libxcb-*.txz
installpkg x/mesa-*.txz
installpkg x/pixman-*.txz
installpkg x/xorgproto-*.txz
## move ldconfig out of the way - links will be set up by doinst.sh
mv /sbin/ldconfig /sbin/ldconfig-bak
installpkg l/glibc-2.29*.txz
mv /sbin/ldconfig-bak /sbin/ldconfig
unset ROOT
cd -
[4] Mount HOST_installation directory to SYSROOT
mount -B $HOST_INSTN $SYSROOT
[5] Set up shell variables
Create a wrapper script for pkg-config which needs to access the libs and headers for the host system. This script sets it up to prefix $SYSROOT to the -L and -I paths in the .pc files.
Exclude coinmp which uses <tuple>-pkg-config in its configure script to define paths in its source code and hence prefixes SYSROOT to those paths. This script will then run with the native PKG_CONFIG_* variables for coinmp.
echo $"[[ ! \$PKG_CONFIG_PATH == *CoinUtils* ]] && {
export PKG_CONFIG_PATH=
export PKG_CONFIG_SYSROOT_DIR=$SYSROOT
export PKG_CONFIG_LIBDIR=$SYSROOT/usr/lib$LIBDIRSUFFIX/pkgconfig
}
exec pkg-config \"\$@\"" > $XGCC_DIR/bin/$HOST-pkg-config
chmod 700 $XGCC_DIR/bin/$HOST-pkg-config
Ref: README.cross - set PYTHON_CFLAGS [Python2]
export PY_INC=$(python -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('INCLUDEPY'));")
export PYTHON_CFLAGS=-I$SYSROOT$PY_INC
export PYTHON_LIBS=-l$(echo $PY_INC | rev | cut -d "/" -f 1 | rev )
## Check:
echo $PYTHON_CFLAGS
echo $PYTHON_LIBS
Add cross tools binaries to the PATH
export PATH=$XGCC_DIR/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
[6] Replace RepositoryModule_build.mk module list with that from RepositoryModule_host.mk.
This probably increases the build time by including unnecessary BUILD platform modules in the build, but to-date I haven't found an alternative to avoid the string of errors, for example:
.../libreoffice-6.3.0.4/solenv/gbuild/ComponentTarget.mk:50: *** No LIBFILENAME set at component target: .../libreoffice-6.3.0.4/workdir_for_build/ComponentTarget/animations/source/animcore/animcore.component. Stop.
… and …
.../libreoffice-6.3.0.4/solenv/gbuild/LinkTarget.mk:687: *** used LinkTarget Library/libopencllo.so not defined. Stop.
etc …
The build time on a dual core 2.2GHz machine is 15+ hours for the cross compilation.
## Test for this having been done already if this is a second build:
[[ ! -s RepositoryModule_build.mk-original ]] && {
mv RepositoryModule_build.mk RepositoryModule_build.mk-original
## .. delete from ..
sed '/add_moduledirs/q' RepositoryModule_build.mk-original > RepositoryModule_build.mk
## .. print section (inclusive)
sed -n '/accessibility/,/xmlsecurity/p' RepositoryModule_host.mk >> RepositoryModule_build.mk
## .. print from (inclusive)
sed -n '/^))/,$p' RepositoryModule_build.mk-original >> RepositoryModule_build.mk
}
Configure options are set with CONFIGURE_OPTS, rather than in an autogen.input file, for inclusion in the cross compilation -⁠-⁠with-⁠build-⁠platform-⁠configure-⁠options parameter. The vcl plugins gen, gtk[2], and gtk3 are included in the build.
Installation is to $DESTDIR for packaging where the prefix for the installed package is set.
NUMJOBS=6 && [[ $(getconf _NPROCESSORS_ONLN) -ge 4 ]] && export NUMJOBS=$[$(getconf _NPROCESSORS_ONLN)*2]
LOCN=en-GB
--with-lang=$LOCN => includes translations submodule
--with-help => includes helpcontent2 submodule => adds $LOCN to off-line help
--with-myspell-dicts => includes dictionaries submodule for spellcheck
export CONFIGURE_OPTS="
--prefix=/
--disable-postgresql-sdbc
--without-java
--without-junit
--disable-odk
--without-krb5
--without-gssapi
--disable-gstreamer-0-10
--disable-gstreamer-1-0
--disable-epm
--enable-release-build
--with-parallelism=$NUMJOBS
--with-locales=$LOCN
--with-lang=$LOCN
--with-help
--with-myspell-dicts
--with-external-tar=/LO_build/external_tarballs
--with-system-libatomic_ops
--with-system-nss
--with-system-libpng
--with-theme=colibre"
Patch for error:
.../RepositoryModule_build.mk:12: *** Module does not exist: .../mysqlc/Module_mysqlc.mk. Stop.
sed -i '/mysqlc/d ' RepositoryModule_build.mk
The build needs plenty of ram and the only way to avoid freezing the build machine may be to enable an additional chunk of swap …
swapon <additional-swap-partition>
Building
When running ./autogen.sh …
Native:
… host_alias == build_alias, which is set by config.guess; the cross-compiling check will be 'no'; and -⁠-⁠with-⁠build-⁠platform-⁠configure-⁠options will be ignored.
Cross:
… host_alias != build_alias; the cross-compiling check will be 'yes'; and -⁠-⁠with-⁠build-⁠platform-⁠configure-⁠options will be used, using or overriding any set for the host platform.
b] For an armv7 cross build, with PYTHON_CFLAGS for the HOST building environment pointing to SYSROOT, this error occurs:
pyport.h ... #error "LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
PYTHON_CFLAGS needs to be set separately for the BUILD platform headers.
c] -⁠-⁠with-⁠build-⁠platform-⁠configure-⁠options
This extract is the section in ./configure which determines the options applying to the BUILD platform build.
They are hard-coded and override any set in CONFIGURE_OPTS and will in turn be overridden by any that follow in -⁠-⁠with-⁠build-⁠platform-⁠configure-⁠options ⇒ sub_conf_opts
sub_conf_opts="$sub_conf_opts $with_build_platform_configure_options"
# Don't bother having configure look for stuff not needed for the build platform anyway
./configure \
--disable-cups \
--disable-gstreamer-1-0 \
--disable-gstreamer-0-10 \
--disable-gtk \
--disable-gtk3 \
--disable-pdfimport \
--disable-postgresql-sdbc \
--with-parallelism="$with_parallelism" \
--without-doxygen \
--without-java \
$sub_conf_opts \
--srcdir=$srcdir \
2>&1
./autogen.sh $CONFIGURE_OPTS --host=$HOST --with-build-platform-configure-options="$CONFIGURE_OPTS PYTHON_CFLAGS=-I$PY_INC --without-help --without-system-dicts" | tee /LO_build/autogen-log-$Arch--$(date +%h_%d_%H:%M)
sed -i 's|check-if-root ||' Makefile
make build-nocheck | tee /LO_build/make-log-$Arch--$(date +%h_%d_%H:%M)
Install to packaging area
DESTDIR=/LO_build/pkg-$Arch make install | tee /LO_build/install-log-$Arch--$(date +%h_%d_%H:%M)
Remove unwanted dictionaries and help files, leaving just $LOCN
rm -rf /LO_build/pkg-$Arch/lib/libreoffice/share/extensions/dict-es
rm -rf /LO_build/pkg-$Arch/lib/libreoffice/share/extensions/dict-fr
rm -rf /LO_build/pkg-$Arch/lib/libreoffice/help/en-US
Remove more unwanted stuff, leaving just en
ls /LO_build/pkg-$Arch/lib/libreoffice/share/{autocorr/*.dat,fingerprint/*lm,numbertext/*sor} | grep -vE "$LOCN|en.lm|en.sor|Roman" \
| while read line
do
rm $line
done
Strip binaries
find /LO_build/pkg-$Arch | xargs file | grep -e "executable" -e "shared object" | grep ELF | cut -f 1 -d : | xargs $STRIP --strip-unneeded
Create package to install to /opt/libreoffice
mkdir -p /LO_build/pkg-$Arch/pkg/opt
mv /LO_build/pkg-$Arch/lib/libreoffice /LO_build/pkg-$Arch/pkg/opt
cd /LO_build/pkg-$Arch/pkg
[[ $Arch == i686 ]] && cp $XGCC_DIR/$HOST/lib/libssp.so.0.0.0 opt/libreoffice/program/libssp.so.0
makepkg -l y -c n /LO_build/libreoffice-$LO_VERSION-$Arch-1.txz
Cross compiling 2 continuing for the other architectures …
/LO_build
├── libreoffice-6.3.3.2
│ ├── workdir_for_build
├── workdir # for host build
.
├── instdir_for_build
├── instdir # for host build
That BUILD platform data can be used for a further HOST platform build, for example build for aarch64 after an armv7 build.
x86_64 BUILD platform build ⇒ armv7 HOST platform build ⇒ armv7 package
↳ remove HOST compiled data …
↳ aarch64 HOST platform build ⇒ aarch64 package
↳ remove HOST compiled data …
↳ i686 HOST platform build ⇒ i686 package
This can result in a significant time saving - built on a 2x quad-core 3GHz machine, the initial armv7 build was ~196 minutes, and by retaining the 'workdir_for_build' and the 'instdir_for_build', the build time was halved for an aarch64 build to ~103 minutes. An x86_64 native only build was ~107 minutes.
[1] (Re)move previous host data:
cd /LO_build/libreoffice-$LO_VERSION
mv workdir workdir-$Arch
mv instdir instdir-$Arch
umount $SYSROOT
mv $XGCC_DIR $XGCC_DIR-$Arch
[2] Set up cross compile for the other architecture
and continue through to 'makepkg'
close
https://hub.libreoffice.org/ReleaseNotes/?LOvers=6.3&LOlocale=en
https://hub.libreoffice.org/donation/?BCP47=en-GB&LOlang=en
mkdir -p ~/.config/libreoffice/4/user/
echo '<?xml version="1.0" encoding="UTF-8"?>
<oor:items xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="FirstRun" oor:op="fuse"><value>false</value></prop></item>
<item oor:path="/org.openoffice.Office.Common/Misc"><prop oor:name="LastTipOfTheDayShown" oor:op="fuse"><value>0</value></prop></item>
<item oor:path="/org.openoffice.Setup/Product"><prop oor:name="LastTimeDonateShown" oor:op="fuse"><value>0</value></prop></item>
<item oor:path="/org.openoffice.Setup/Product"><prop oor:name="ooSetupLastVersion" oor:op="fuse"><value>6.3</value></prop></item>
</oor:items>' > ~/.config/libreoffice/4/user/registrymodifications.xcu
then for each new start …
sed -i 's|LastTipOfTheDayShown.*$|LastTipOfTheDayShown" oor:op="fuse"><value>0</value></prop></item>|;s|LastTimeDonateShown.*$|LastTimeDonateShown" oor:op="fuse"><value>0</value></prop></item>|' ~/.config/libreoffice/4/user/registrymodifications.xcu
SAL_USE_VCLPLUGIN=gtk /opt/libreoffice/program/soffice --calc
When running LO 6.3.3.2 with the gen or gtk vcl plugin, the Tip of the Day text doesn't wrap in the dialog box if the text is selectable - my preference is wrapping text, so until bug 128524 is resolved:
sed -i 's|selectable">True|selectable">False|' /opt/libreoffice/share/config/soffice.cfg/cui/ui/tipofthedaydialog.ui
git clone https://github.com/Ray-V/LOcrossbuild.git
cd LOcrossbuild
git checkout gh-pages