From b4f6921e4af7f25b05f0ed2f9659f75e7a6f33b5 Mon Sep 17 00:00:00 2001 From: Hein-Pieter van Braam-Stewart Date: Sat, 6 Feb 2021 08:52:18 +0100 Subject: [PATCH] Add linux toolchain for windows build --- .gitignore | 1 + ...erfile.builder => Dockerfile.linux-builder | 0 Dockerfile.windows-builder | 6 + build-sdk.sh | 63 +++-- build-windows.sh | 216 ++++++++++++++++++ clean-linux-toolchain.sh | 8 + installer.nsis | 26 +++ pkg-config.bat | 2 + 8 files changed, 308 insertions(+), 14 deletions(-) rename Dockerfile.builder => Dockerfile.linux-builder (100%) create mode 100644 Dockerfile.windows-builder create mode 100755 build-windows.sh create mode 100644 installer.nsis create mode 100644 pkg-config.bat diff --git a/.gitignore b/.gitignore index 14787b9c37..137328aa64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /output /dl /godot-toolchains +/windows-build /.auto.deps /.config.cmd /.config.old diff --git a/Dockerfile.builder b/Dockerfile.linux-builder similarity index 100% rename from Dockerfile.builder rename to Dockerfile.linux-builder diff --git a/Dockerfile.windows-builder b/Dockerfile.windows-builder new file mode 100644 index 0000000000..50aa4fd5d6 --- /dev/null +++ b/Dockerfile.windows-builder @@ -0,0 +1,6 @@ +FROM fedora:33 + +RUN dnf -y install mingw32-nsis xz bzip2 zip diffutils texinfo gcc gcc-c++ make mingw64-winpthreads mingw64-winpthreads-static mingw64-gcc mingw64-gcc-c++ curl && \ + dnf clean all + +COPY build-windows.sh /usr/local/bin diff --git a/build-sdk.sh b/build-sdk.sh index 04c96fe23f..8f250bf86c 100755 --- a/build-sdk.sh +++ b/build-sdk.sh @@ -2,15 +2,29 @@ set -e function usage() { - echo "usage: $0 i686|x86_64|armv7" + echo "usage: $0 host target" + echo " where host is one of linux-x86_64, windows-x86_64" + echo " where target is one of i686, x86_64, armv7" exit 1 } -if [ -z $1 ]; then +if [ -z $1 ] || [ -z $1 ]; then usage fi case $1 in + linux-x86_64) + host=$1 + ;; + windows-x86_64) + host=$1 + ;; + *) + echo "unknown SDK host \"$1\"" + usage +esac + +case $2 in i686) cp config-godot-i686 .config toolchain_prefix=i686-godot-linux-gnu @@ -27,6 +41,7 @@ case $1 in bits=32 ;; *) + echo "unknown SDK target \"$2\"" usage ;; esac @@ -40,22 +55,42 @@ else exit 1 fi -${container} build -f Dockerfile.builder -t godot-buildroot-builder -${container} run -it --rm -v $(pwd):/tmp/buildroot -w /tmp/buildroot -e FORCE_UNSAFE_CONFIGURE=1 --userns=keep-id godot-buildroot-builder scl enable devtoolset-9 "bash -c make syncconfig; make clean sdk" +function build_linux_sdk() { + ${container} build -f Dockerfile.linux-builder -t godot-buildroot-builder-linux + ${container} run -it --rm -v $(pwd):/tmp/buildroot -w /tmp/buildroot -e FORCE_UNSAFE_CONFIGURE=1 --userns=keep-id godot-buildroot-builder scl enable devtoolset-9 "bash -c make syncconfig; make clean sdk" -mkdir -p godot-toolchains + mkdir -p godot-toolchains + + rm -fr godot-toolchains/${toolchain_prefix}_sdk-buildroot + tar xf output/images/${toolchain_prefix}_sdk-buildroot.tar.gz -C godot-toolchains + + pushd godot-toolchains/${toolchain_prefix}_sdk-buildroot + ../../clean-linux-toolchain.sh ${toolchain_prefix} ${bits} + popd + + pushd godot-toolchains + tar -cjf ${toolchain_prefix}_sdk-buildroot.tar.bz2 ${toolchain_prefix}_sdk-buildroot + rm -rf ${toolchain_prefix}_sdk-buildroot + popd +} -rm -fr godot-toolchains/${toolchain_prefix}_sdk-buildroot -tar xf output/images/${toolchain_prefix}_sdk-buildroot.tar.gz -C godot-toolchains +function build_windows_sdk() { + ${container} build -f Dockerfile.windows-builder -t godot-buildroot-builder-windows -pushd godot-toolchains/${toolchain_prefix}_sdk-buildroot -../../clean-linux-toolchain.sh ${toolchain_prefix} ${bits} -popd + if [ ! -e godot-toolchains/${toolchain_prefix}_sdk-buildroot.tar.bz2 ]; then + build_linux_sdk + fi -pushd godot-toolchains -tar -cjf ${toolchain_prefix}_sdk-buildroot.tar.bz2 ${toolchain_prefix}_sdk-buildroot -rm -rf ${toolchain_prefix}_sdk-buildroot -popd + ${container} run -it --rm -v $(pwd):/tmp/buildroot -w /tmp/buildroot --userns=keep-id godot-buildroot-builder-windows bash -x /usr/local/bin/build-windows.sh ${toolchain_prefix} +} + +if [ "${host}" == "linux-x86_64" ]; then + build_linux_sdk +fi + +if [ "${host}" == "windows-x86_64" ]; then + build_windows_sdk +fi echo echo "***************************************" diff --git a/build-windows.sh b/build-windows.sh new file mode 100755 index 0000000000..d9f761925e --- /dev/null +++ b/build-windows.sh @@ -0,0 +1,216 @@ +#!/bin/bash + +set -e + +binutils_ver=2.35.1 +gcc_ver=10.2.0 +mpc_ver=1.2.1 +mpfr_ver=4.1.0 +gmp_ver=6.2.1 +isl_ver=0.18 +scons_local_ver=4.1.0 +sevenz_ver=1900 +# GNU Make 4.3 cannot be cross compiled +make_ver=4.2.1 + +binutils_file=binutils-${binutils_ver}.tar.xz +binutils_url=https://ftp.gnu.org/gnu/binutils/${binutils_file} + +gcc_file=gcc-${gcc_ver}.tar.xz +gcc_url=https://ftp.gnu.org/gnu/gcc/gcc-${gcc_ver}/${gcc_file} + +mpc_file=mpc-${mpc_ver}.tar.gz +mpc_url=https://ftp.gnu.org/gnu/mpc/${mpc_file} + +mpfr_file=mpfr-${mpfr_ver}.tar.xz +mpfr_url=https://ftp.gnu.org/gnu/mpfr/${mpfr_file} + +gmp_file=gmp-${gmp_ver}.tar.xz +gmp_url=https://ftp.gnu.org/gnu/gmp/${gmp_file} + +isl_file=isl-${isl_ver}.tar.bz2 +isl_url=https://gcc.gnu.org/pub/gcc/infrastructure/${isl_file} + +scons_local_file=scons-local-${scons_local_ver}.zip +scons_local_url=https://sourceforge.net/projects/scons/files/${scons_local_file} + +make_file=make-${make_ver}.tar.gz +make_url=http://ftp.gnu.org/gnu/make/${make_file} + +case $1 in + arm-godot-linux-gnueabihf) + ;; + i686-godot-linux-gnu) + ;; + x86_64-godot-linux-gnu) + ;; + *) + echo "usage: $0 " + echo "tuple can be one of : arm-godot-linux-gnueabihf, i686-godot-linux-gnu, x86_64-godot-linux-gnu" + exit 1 + ;; +esac + +target_arch=$1 +godot_toolchain_dir="$(pwd)/godot-toolchains" +base_dir="$(pwd)/windows-build" +target_dir="${base_dir}/${target_arch}_sdk-buildroot" + +function unpack_linux_sdk() { + mkdir -p "${base_dir}" + tar xf "${godot_toolchain_dir}/${target_arch}_sdk-buildroot.tar.bz2" -C "${base_dir}" +} + +function pack_windows_sdk() { + pushd "${target_dir}/bin" + cp ${base_dir}/../pkg-config.bat . + unzip "${base_dir}/download/${scons_local_file}" + popd + + pushd "${target_dir}" + for link in $(find -type l); do + echo "mklink \"${link}\" \"$(readlink ${link})\"" >> fix-sdk.bat + rm "${link}" + done + + echo "mklink \"bin/gcc.exe\" \"${target_arch}-gcc.exe\"" >> fix-sdk.bat + echo "mklink \"bin/g++.exe\" \"${target_arch}-g++.exe\"" >> fix-sdk.bat + echo "mklink \"bin/ar.exe\" \"${target_arch}-ar.exe\"" >> fix-sdk.bat + echo "mklink \"bin/ranlib.exe\" \"${target_arch}-ranlib.exe\"" >> fix-sdk.bat + echo "mklink \"bin/gcc-ar.exe\" \"${target_arch}-gcc-ar.exe\"" >> fix-sdk.bat + echo "mklink \"bin/gcc-ranlib.exe\" \"${target_arch}-gcc-ranlib.exe\"" >> fix-sdk.bat + echo "mklink \"bin/lto-wrapper.exe\" \"../libexec/gcc/${target_arch}/${gcc_ver}/lto-wrapper.exe\"" >> fix-sdk.bat + popd + + pushd ${base_dir} + cat ../installer.nsis | sed -e "s/TARGET_ARCH/${target_arch}/g" > installer.nsis + makensis installer.nsis + mv "Godot-SDK-${target_arch}.exe" ../godot-toolchains + popd +} + +function download() { + mkdir -p "${base_dir}/download" + + for component in make scons_local binutils gcc mpc mpfr gmp isl; do + component_file=${component}_file + component_url=${component}_url + if [ ! -e "${base_dir}/download/${!component_file}" ]; then + curl -L ${!component_url} --output "${base_dir}/download/${!component_file}" + fi + done +} + +function unpack() { + mkdir -p "${base_dir}/src" + + if [ ! -e "${base_dir}/src/gcc" ]; then + mkdir -p "${base_dir}/src/gcc" + pushd "${base_dir}/src/gcc" + tar --strip-components=1 -xf "${base_dir}/download/${gcc_file}" + for component in mpc mpfr gmp isl; do + component_file=${component}_file + mkdir ${component} + pushd $component + tar --strip-components=1 -xf "${base_dir}/download/${!component_file}" + popd + done + popd + fi + + if [ ! -e "${base_dir}/src/binutils" ]; then + mkdir -p "${base_dir}/src/binutils" + pushd "${base_dir}/src/binutils" + tar --strip-components=1 -xf "${base_dir}/download/${binutils_file}" + popd + fi + + if [ ! -e "${base_dir}/src/make" ]; then + mkdir -p "${base_dir}/src/make" + pushd "${base_dir}/src/make" + tar --strip-components=1 -xf "${base_dir}/download/${make_file}" + popd + fi +} + +function build_gcc() { + + mkdir -p "${base_dir}/build" + rm -rf "${base_dir}/build/gcc" + mkdir -p "${base_dir}/build/gcc" + pushd "${base_dir}/build/gcc" + + "${base_dir}/src/gcc/configure" --prefix=${target_dir} --sysconfdir=${target_dir}/etc --enable-static --host=x86_64-w64-mingw32 --build=x86_64-linux-gnu --target=${target_arch} --with-sysroot=${target_dir}/${target_arch}/sysroot --enable-__cxa_atexit --with-gnu-ld --disable-libssp --disable-multilib --disable-decimal-float --without-zstd --enable-libquadmath --enable-tls --enable-threads --with-arch=nocona --enable-languages=c,c++ --enable-shared --disable-libgomp --disable-libstdcxx --with-static-standard-libraries LDFLAGS="-lssp" + make -j + make install-strip + popd +} + +function build_binutils() { + + mkdir -p "${base_dir}/build" + rm -rf "${base_dir}/build/binutils" + mkdir -p "${base_dir}/build/binutils" + pushd "${base_dir}/build/binutils" + + "${base_dir}/src/binutils/configure" --with-static-standard-libraries --prefix=${target_dir} --with-sysroot=${target_dir}/${target_arch}/sysroot --enable-lto --host=x86_64-w64-mingw32 --build=x86_64-linux-gnu --target=${target_arch} LDFLAGS="-lssp" + make -j + make install-strip + popd +} + +function build_make() { + + mkdir -p "${base_dir}/build" + rm -rf "${base_dir}/build/make" + mkdir -p "${base_dir}/build/make" + pushd "${base_dir}/build/make" + + "${base_dir}/src/make/configure" --prefix=${target_dir} --host=x86_64-w64-mingw32 --build=x86_64-linux-gnu LDFLAGS="-lssp" + make -j + make install-strip + popd +} + +function cleanup_sdk() { + rm -f "${target_dir}/relocate-sdk.sh" + + for directory in $(find ${target_dir} -name *.exe -printf %h\\n | sort -u); do + cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libssp-0.dll ${directory} + cp /usr/x86_64-w64-mingw32/sys-root/mingw/bin/libwinpthread-1.dll ${directory} + done + + while read -r file; do + rm -f $(echo $file | sed -e 's/\.exe$//') + done < <(find ${target_dir} -name *.exe) + + while read -r file; do + rm -f $(echo $file | sed -e 's/\.dll$/.so/') + done < <(find ${target_dir} -name *.dll) + + find ${target_dir}/bin -type l -delete + find ${target_dir}/bin -name 'python*' -delete + + # Filename case issues, kind of breaks the SDK for some uses but probably OK + rm -rf "${target_dir}/${target_arch}/sysroot/usr/include/linux/netfilter" + rm -rf "${target_dir}/${target_arch}/sysroot/usr/include/linux/netfilter_ipv4" + rm -rf "${target_dir}/${target_arch}/sysroot/usr/include/linux/netfilter_ipv6" + + rm -rf ${target_dir}/lib/python* +} + +export PATH=${target_dir}/bin:${PATH} +export HOSTCC=${target_arch}-gcc +export HOSTCXX=${target_arch}-g++ + +rm -rf "${target_dir}" + +download +unpack +unpack_linux_sdk +build_make +build_binutils +build_gcc + +cleanup_sdk +pack_windows_sdk diff --git a/clean-linux-toolchain.sh b/clean-linux-toolchain.sh index d63a566a84..7447dbdcfe 100755 --- a/clean-linux-toolchain.sh +++ b/clean-linux-toolchain.sh @@ -89,3 +89,11 @@ if [ -L ${arch}/sysroot/usr/${libdir_to_keep} ]; then fi find -name *python2* -exec rm -rf {} \; || true + +ln -s bin/gcc ${arch}-gcc +ln -s bin/g++ ${arch}-g++ +ln -s bin/ar ${arch}-ar +ln -s bin/ranlib ${arch}-ranlib +ln -s bin/gcc-ar ${arch}-gcc-ar +ln -s bin/gcc-ranlib ${arch}-gcc-ranlib + diff --git a/installer.nsis b/installer.nsis new file mode 100644 index 0000000000..f6b4af9359 --- /dev/null +++ b/installer.nsis @@ -0,0 +1,26 @@ +Name "Godot SDK for TARGET_ARCH" +OutFile "Godot-SDK-TARGET_ARCH.exe" +InstallDir "$ProgramFiles\Godot SDKs\TARGET_ARCH" +InstallDirRegKey HKLM SOFTWARE\ "Install_Dir" + +ShowInstDetails hide +ShowUninstDetails hide + +XPStyle on + +Page directory +Page instfiles + +DirText "Please select the installation folder." + +Section "" + SectionIn RO + + SetOutPath "$INSTDIR" + File /r "TARGET_ARCH_sdk-buildroot/*.*" +SectionEnd + +Section -post + ExecShell "" "$INSTDIR\fix-sdk.bat" +SectionEnd + diff --git a/pkg-config.bat b/pkg-config.bat new file mode 100644 index 0000000000..d97b31eaeb --- /dev/null +++ b/pkg-config.bat @@ -0,0 +1,2 @@ +@echo off +echo -lXcursor -lXinerama -lXext -lXrandr -lXrender -lX11 -lXi -lasound -ludev -D_REENTRANT -lpulse -ldl