Skip to content

Instantly share code, notes, and snippets.

@silverkorn
Last active December 30, 2020 23:26
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save silverkorn/f0566819025d4a4882b82b2b27d20826 to your computer and use it in GitHub Desktop.
Save silverkorn/f0566819025d4a4882b82b2b27d20826 to your computer and use it in GitHub Desktop.
Godot Engine cross-compiling helper attempt for Linux x11 ARM (and potentially others).
#!/usr/bin/env bash
function usage() {
echo "Usage: $(basename $0) TARGET_ARCH TARGET_OS [SCONSOPTS]"
echo "Helper to cross-compile Godot game engine [https://godotengine.org/] on other Linux architectures.".
echo
echo "The TARGET_ARCH is the target architecture/device to compile to."
echo " List of available TARGET_ARCH"
echo " rpi2"
echo " rpi3"
echo "The TARGET_OS is the target operating system to compile to and/or the gather dynamic libraries from for the cross-compilation."
echo " List of available TARGET_OS"
echo " raspbian"
echo "The SCONSOPTS is the typical `scons` options you want to your build."
echo
exit 1;
}
function GetDynamicLibsFromOS() {
targetOS=$1
targetTriple=$2
targetDistribArch=$3
case ${targetOS} in
raspbian)
basePoolURL="https://archive.raspbian.org/raspbian/pool/main"
# Main dependencies
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/a/alsa-lib/libasound2_1.1.7-1_${targetDistribArch}.deb libasound
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/f/freetype/libfreetype6_2.8.1-2_${targetDistribArch}.deb libfreetype
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/o/openssl/libssl1.1_1.1.1-2_${targetDistribArch}.deb libssl libcrypto
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libx11/libx11-6_1.6.7-1_${targetDistribArch}.deb libX11
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcursor/libxcursor1_1.1.15-1_${targetDistribArch}.deb libXcursor
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxinerama/libxinerama1_1.1.4-1_${targetDistribArch}.deb libXinerama
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxrandr/libxrandr2_1.5.1-1_${targetDistribArch}.deb libXrandr
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/m/mbedtls/libmbedtls12_2.13.0-3_${targetDistribArch}.deb libmbedtls
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/m/mesa/libgl1-mesa-glx_18.1.9-1_${targetDistribArch}.deb libGL
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/p/pulseaudio/libpulse0_12.2-2+b2_${targetDistribArch}.deb libpulse libpulse-simple pulseaudio/libpulsecommon-11.0
# Dependencies to main dependencies
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/a/attr/libattr1_2.4.47-2_${targetDistribArch}.deb libattr
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/d/dbus/libdbus-1-3_1.12.10-1_${targetDistribArch}.deb libdbus-1
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/e/expat/libexpat1_2.2.6-1_${targetDistribArch}.deb libexpat
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/f/flac/libflac8_1.3.2-3_${targetDistribArch}.deb libFLAC
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/l/lz4/liblz4-1_1.8.2-1+rpi1_${targetDistribArch}.deb liblz4
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/liba/libasyncns/libasyncns0_0.8-6_${targetDistribArch}.deb libasyncns
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libb/libbsd/libbsd0_0.9.1-1_${targetDistribArch}.deb libbsd
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libc/libcap2/libcap2_2.25-1.2_${targetDistribArch}.deb libcap
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libd/libdrm/libdrm2_2.4.95-1+rpi1_${targetDistribArch}.deb libdrm
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libg/libgcrypt20/libgcrypt20_1.8.4-3_${targetDistribArch}.deb libgcrypt
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libg/libgpg-error/libgpg-error0_1.32-3_${targetDistribArch}.deb libgpg-error
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libi/libice/libice6_1.0.9-2_${targetDistribArch}.deb libICE
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libo/libogg/libogg0_1.3.2-1_${targetDistribArch}.deb libogg
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libs/libselinux/libselinux1_2.8-1_${targetDistribArch}.deb libselinux
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libs/libsm/libsm6_1.2.2-1+b3_${targetDistribArch}.deb libSM
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libs/libsndfile/libsndfile1_1.0.28-4_${targetDistribArch}.deb libsndfile
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libv/libvorbis/libvorbis0a_1.3.6-1_${targetDistribArch}.deb libvorbis
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libv/libvorbis/libvorbisenc2_1.3.6-1_${targetDistribArch}.deb libvorbisenc
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libx11/libx11-xcb1_1.6.7-1_${targetDistribArch}.deb libX11-xcb
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxau/libxau6_1.0.8-1+b2_${targetDistribArch}.deb libXau
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcb/libxcb-dri2-0_1.13.1-1_${targetDistribArch}.deb libxcb-dri2
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcb/libxcb-dri3-0_1.13.1-1_${targetDistribArch}.deb libxcb-dri3
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcb/libxcb-glx0_1.13.1-1_${targetDistribArch}.deb libxcb-glx
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcb/libxcb-present0_1.13.1-1_${targetDistribArch}.deb libxcb-present
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcb/libxcb-sync1_1.13.1-1_${targetDistribArch}.deb libxcb-sync
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxcb/libxcb1_1.13.1-1_${targetDistribArch}.deb libxcb
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxdamage/libxdamage1_1.1.4-3_${targetDistribArch}.deb libXdamage
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxdmcp/libxdmcp6_1.1.2-3_${targetDistribArch}.deb libXdmcp
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxext/libxext6_1.3.3-1+b2_${targetDistribArch}.deb libXext
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxfixes/libxfixes3_5.0.1-2+deb8u1_${targetDistribArch}.deb libXfixes
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxi/libxi6_1.7.9-1_${targetDistribArch}.deb libXi
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxrender/libxrender1_0.9.10-1_${targetDistribArch}.deb libXrender
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxshmfence/libxshmfence1_1.3-1_${targetDistribArch}.deb libxshmfence
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxtst/libxtst6_1.2.3-1_${targetDistribArch}.deb libXtst
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/libx/libxxf86vm/libxxf86vm1_1.1.4-1+b2_${targetDistribArch}.deb libXxf86vm
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/m/mbedtls/libmbedcrypto3_2.13.0-3_${targetDistribArch}.deb libmbedcrypto
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/m/mbedtls/libmbedx509-0_2.13.0-3_${targetDistribArch}.deb libmbedx509
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/m/mesa/libglapi-mesa_18.1.9-1_${targetDistribArch}.deb libglapi
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/p/pcre3/libpcre3_8.39-11+rpi1_${targetDistribArch}.deb libpcre
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/s/systemd/libsystemd0_239-10+rpi1_${targetDistribArch}.deb libsystemd
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/t/tcp-wrappers/libwrap0_7.6.q-27_${targetDistribArch}.deb libwrap
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/u/util-linux/libuuid1_2.32.1-0.1_${targetDistribArch}.deb libuuid
GetDynamicLibFromDebianPool ${targetTriple} ${basePoolURL}/x/xz-utils/liblzma5_5.2.2-1.3_${targetDistribArch}.deb liblzma
;;
esac
}
function GetDynamicLibFromDebianPool() {
targetTriple=$1
debPackageURL=$2
mainLibraryName=$3
shift; shift; shift
additionnalLibrariesNames=$@
targetLibDir=/usr/lib/${targetTriple}
[ ! -d "${targetLibDir}" ] && mkdir -p "${targetLibDir}" 2>&1 > /dev/null
if [ ! -e "${targetLibDir}/${mainLibraryName}.so" ];
then
echo -e "\e[93mGetting library '${mainLibraryName}'...\e[39m"
mkdir -p "/tmp/lib/${targetTriple}/${mainLibraryName}" 2> /dev/null && \
pushd "/tmp/lib/${targetTriple}/${mainLibraryName}" > /dev/null && \
wget --quiet -O package.deb "${debPackageURL}" > /dev/null && \
dpkg -x package.deb ./ > /dev/null && \
packageLibDir=lib
[ ! -d "/tmp/lib/${targetTriple}/${mainLibraryName}/${packageLibDir}" ] && packageLibDir=usr/lib
cp -f "${packageLibDir}/${targetTriple}/"*".so"* "${targetLibDir}/" && \
cp -f "${packageLibDir}/${targetTriple}/"*"/"*".so"* "${targetLibDir}/" 2> /dev/null
for libraryLatest in $(find "${targetLibDir}/" -iname "${mainLibraryName}.so.*" -exec basename {} \;); do
ln -f -s $libraryLatest "${targetLibDir}/${mainLibraryName}.so"
done
if [ "${additionnalLibrariesNames}" != "" ];
then
for libraryName in ${additionnalLibrariesNames}; do
libraryName=$(basename ${libraryName})
for libraryLatest in $(find "${targetLibDir}/" -iname "${libraryName}.so.*" -exec basename {} \;); do
ln -f -s $libraryLatest "${targetLibDir}/${libraryName}.so"
done
done
fi
popd > /dev/null
rm -f -R "/tmp/lib/${targetTriple}/${libraryName}"
fi
}
if [ $# -le 1 ];
then
usage
fi
CROSS=
CROSSFLAGS=
ARCH=
TARGET_ARCH=$1
TARGET_OS=$2
shift; shift
SCONSOPTS=$@
#SCONSOPTS=$*
case $TARGET_ARCH in
rpi2)
CROSS=arm-linux-gnueabihf
ARCH=arm
DISTRIB_ARCH=armhf
CROSSFLAGS='-D__ARM_ARCH_7__ -D__ARM_ARCH_7A__ -D__ARM_NEON__ -DGLES2_ENABLED -march=armv7-a -mtune=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard'
SCONSOPTS="${SCONSOPTS} CCFLAGS='${CROSSFLAGS}' CPPFLAGS='${CROSSFLAGS}' arch=${ARCH}"
SCONSOPTS="${SCONSOPTS} builtin_freetype=yes"
;;
rpi3)
CROSS=arm-linux-gnueabihf
ARCH=arm
DISTRIB_ARCH=armhf
CROSSFLAGS='-D__ARM_ARCH_8A__ -DGLES2_ENABLED -march=armv8-a -mtune=cortex-a53 -mfpu=neon-fp-armv8 -mfloat-abi=hard'
SCONSOPTS="${SCONSOPTS} CCFLAGS='${CROSSFLAGS}' CPPFLAGS='${CROSSFLAGS}' arch=${ARCH}"
SCONSOPTS="${SCONSOPTS} builtin_freetype=yes"
;;
*)
echo "Target architecture/device/OS not available."
exit 1;
;;
esac
# Set the cross-compiling tools and libraries directory for scons
SCONSOPTS="${SCONSOPTS} CC='${CROSS}-gcc' CXX='${CROSS}-g++' LINKFLAGS='-L/usr/${CROSS}/lib -L/usr/lib/${CROSS}'"
# Install dependencies
if [ "$(which apt-get 2> /dev/null | wc -l)" == "1" ]; then
apt-get -y install dpkg wget build-essential binutils binutils-${CROSS} gcc-${CROSS} g++-${CROSS} > /dev/null
# [TODO: Find arm-linux-gnueabi toolchains w/ hard-float for RHEL/CentOS/Fedora]
#elif [ "$(which yum 2> /dev/null | wc -l)" == "1" ]; then
# yum groupinstall 'Development Tools' > /dev/null
# yum -y install dpkg wget binutils binutils-${CROSS} gcc-${CROSS} g++-${CROSS} > /dev/null
fi
# Download dependencies
GetDynamicLibsFromOS ${TARGET_OS} ${CROSS} ${DISTRIB_ARCH}
# Godot compilation
eval scons ${SCONSOPTS}
@silverkorn
Copy link
Author

silverkorn commented Oct 4, 2018

Quick command usage example:

cd "${GODOT_PATH}"
wget https://gist.githubusercontent.com/silverkorn/f0566819025d4a4882b82b2b27d20826/raw/godot-cross-compile.sh
sudo chmod u+x godot-cross-compile.sh
sudo ./godot-cross-compile.sh rpi3 raspbian platform=x11 -j 4

@silverkorn
Copy link
Author

Might need to change the "-mfloat-abi=hard" to "-mfloat-abi=softfp" since they have "-mfpu=neon"?
https://wiki.debian.org/ArmHardFloatPort

@phansonloc1999
Copy link

phansonloc1999 commented Apr 14, 2020

Uh, what version of Godot and Scons did you use for this to work? If possible, can you kindly provide a pre-built binary of Godot >= 3.1 for RPi3 :D? Thanks.

@silverkorn
Copy link
Author

Unfortunately it doesn't work properly due to some build steps.
(See godotengine/godot#23506 + godotengine/godot#23575)

There's a project to build more properly (godotengine/godot#24030).

Otherwise, you might want to take a look at Dockcross (https://github.com/dockcross/dockcross), there's a list of ARM-target toolchains available there. I haven't tried it yet but I might work... To test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment