diff --git a/.docker/cross/aarch64.Dockerfile b/.docker/cross/aarch64.Dockerfile new file mode 100644 index 000000000..6dfb5bdaa --- /dev/null +++ b/.docker/cross/aarch64.Dockerfile @@ -0,0 +1,44 @@ +FROM ubuntu:18.04 +ARG DEBIAN_FRONTEND=noninteractive + +COPY common.sh lib.sh / +RUN /common.sh + +COPY cmake.sh / +RUN /cmake.sh + +COPY xargo.sh / +RUN /xargo.sh + +RUN apt-get update && apt-get install --assume-yes --no-install-recommends \ + g++-aarch64-linux-gnu \ + libc6-dev-arm64-cross + +COPY deny-debian-packages.sh / +RUN TARGET_ARCH=arm64 /deny-debian-packages.sh \ + binutils \ + binutils-aarch64-linux-gnu + +COPY qemu.sh / +RUN /qemu.sh aarch64 softmmu + +COPY dropbear.sh / +RUN /dropbear.sh + +COPY linux-image.sh / +RUN /linux-image.sh aarch64 + +COPY linux-runner / + +ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \ + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUNNER="/linux-runner aarch64" \ + CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \ + CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ \ + BINDGEN_EXTRA_CLANG_ARGS_aarch64_unknown_linux_gnu="--sysroot=/usr/aarch64-linux-gnu" \ + QEMU_LD_PREFIX=/usr/aarch64-linux-gnu \ + RUST_TEST_THREADS=1 \ + PKG_CONFIG_PATH="/usr/lib/aarch64-linux-gnu/pkgconfig/:${PKG_CONFIG_PATH}" + +RUN dpkg --add-architecture arm64 +RUN apt-get update +RUN apt-get install --assume-yes --no-install-recommends libssl-dev:arm64 libdbus-1-dev:arm64 libsoup2.4-dev:arm64 libssl-dev:arm64 libgtk-3-dev:arm64 webkit2gtk-4.0-dev:arm64 libappindicator3-1:arm64 librsvg2-dev:arm64 patchelf:arm64 diff --git a/.docker/cross/cmake.sh b/.docker/cross/cmake.sh new file mode 100755 index 000000000..9ed4ee6a0 --- /dev/null +++ b/.docker/cross/cmake.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +# shellcheck disable=SC1091 +. lib.sh + +main() { + local version=3.23.1 + + install_packages curl + + local td + td="$(mktemp -d)" + + pushd "${td}" + + curl --retry 3 -sSfL "https://github.com/Kitware/CMake/releases/download/v${version}/cmake-${version}-linux-x86_64.sh" -o cmake.sh + sh cmake.sh --skip-license --prefix=/usr/local + + popd + + purge_packages + + rm -rf "${td}" + rm -rf /var/lib/apt/lists/* + rm "${0}" +} + +main "${@}" diff --git a/.docker/cross/common.sh b/.docker/cross/common.sh new file mode 100755 index 000000000..24d56194d --- /dev/null +++ b/.docker/cross/common.sh @@ -0,0 +1,40 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +# shellcheck disable=SC1091 +. lib.sh + +# For architectures except amd64 and i386, look for packages on ports.ubuntu.com instead. +# This is important if you enable additional architectures so you can install libraries to cross-compile against. +# Look for 'dpkg --add-architecture' in the README for more details. +if grep -i ubuntu /etc/os-release >/dev/null; then + sed 's/http:\/\/\(.*\).ubuntu.com\/ubuntu\//[arch-=amd64,i386] http:\/\/ports.ubuntu.com\/ubuntu-ports\//g' /etc/apt/sources.list > /etc/apt/sources.list.d/ports.list + sed -i 's/http:\/\/\(.*\).ubuntu.com\/ubuntu\//[arch=amd64,i386] http:\/\/\1.archive.ubuntu.com\/ubuntu\//g' /etc/apt/sources.list +fi + +install_packages \ + autoconf \ + automake \ + binutils \ + ca-certificates \ + curl \ + file \ + gcc \ + git \ + libtool \ + m4 \ + make + +if_centos install_packages \ + clang-devel \ + gcc-c++ \ + glibc-devel \ + pkgconfig + +if_ubuntu install_packages \ + g++ \ + libc6-dev \ + libclang-dev \ + pkg-config diff --git a/.docker/cross/deny-debian-packages.sh b/.docker/cross/deny-debian-packages.sh new file mode 100755 index 000000000..3193333e9 --- /dev/null +++ b/.docker/cross/deny-debian-packages.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +main() { + local package + + for package in "${@}"; do + echo "Package: ${package}:${TARGET_ARCH} +Pin: release * +Pin-Priority: -1" > "/etc/apt/preferences.d/${package}" + echo "${package}" + done + + rm "${0}" +} + +main "${@}" diff --git a/.docker/cross/dropbear.sh b/.docker/cross/dropbear.sh new file mode 100755 index 000000000..097814e86 --- /dev/null +++ b/.docker/cross/dropbear.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +# shellcheck disable=SC1091 +. lib.sh + +main() { + local version=2022.82 + + install_packages \ + autoconf \ + automake \ + bzip2 \ + curl \ + make + + if_centos install_packages zlib-devel + if_ubuntu install_packages zlib1g-dev + + local td + td="$(mktemp -d)" + + pushd "${td}" + + curl --retry 3 -sSfL "https://matt.ucc.asn.au/dropbear/releases/dropbear-${version}.tar.bz2" -O + tar --strip-components=1 -xjf "dropbear-${version}.tar.bz2" + + # Remove some unwanted message + sed -i '/skipping hostkey/d' cli-kex.c + sed -i '/failed to identify current user/d' cli-runopts.c + + ./configure \ + --disable-syslog \ + --disable-shadow \ + --disable-lastlog \ + --disable-utmp \ + --disable-utmpx \ + --disable-wtmp \ + --disable-wtmpx \ + --disable-pututline \ + --disable-pututxline + + make "-j$(nproc)" PROGRAMS=dbclient + cp dbclient /usr/local/bin/ + + purge_packages + + popd + + rm -rf "${td}" + rm "${0}" +} + +main "${@}" diff --git a/.docker/cross/lib.sh b/.docker/cross/lib.sh new file mode 100644 index 000000000..0d299b8a6 --- /dev/null +++ b/.docker/cross/lib.sh @@ -0,0 +1,45 @@ +purge_list=() + +install_packages() { + if grep -i ubuntu /etc/os-release; then + apt-get update + + for pkg in "${@}"; do + if ! dpkg -L "${pkg}" >/dev/null 2>/dev/null; then + apt-get install --assume-yes --no-install-recommends "${pkg}" + + purge_list+=( "${pkg}" ) + fi + done + else + for pkg in "${@}"; do + if ! yum list installed "${pkg}" >/dev/null 2>/dev/null; then + yum install -y "${pkg}" + + purge_list+=( "${pkg}" ) + fi + done + fi +} + +purge_packages() { + if (( ${#purge_list[@]} )); then + if grep -i ubuntu /etc/os-release; then + apt-get purge --assume-yes --auto-remove "${purge_list[@]}" + else + yum remove -y "${purge_list[@]}" + fi + fi +} + +if_centos() { + if grep -q -i centos /etc/os-release; then + eval "${@}" + fi +} + +if_ubuntu() { + if grep -q -i ubuntu /etc/os-release; then + eval "${@}" + fi +} diff --git a/.docker/cross/linux-image.sh b/.docker/cross/linux-image.sh new file mode 100755 index 000000000..dc85ed45c --- /dev/null +++ b/.docker/cross/linux-image.sh @@ -0,0 +1,274 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +# shellcheck disable=SC1091 +. lib.sh + +main() { + # arch in the rust target + local arch="${1}" \ + kversion=4.19.0-20 + + local debsource="deb http://http.debian.net/debian/ buster main" + debsource="${debsource}\ndeb http://security.debian.org/ buster/updates main" + + local dropbear="dropbear-bin" + + local -a deps + local kernel= + local libgcc="libgcc1" + + # select debian arch and kernel version + case "${arch}" in + aarch64) + arch=arm64 + kernel="${kversion}-arm64" + ;; + armv7) + arch=armhf + kernel="${kversion}-armmp" + ;; + i686) + arch=i386 + kernel="${kversion}-686" + ;; + mips|mipsel) + kernel="${kversion}-4kc-malta" + ;; + mips64el) + kernel="${kversion}-5kc-malta" + ;; + powerpc) + # there is no buster powerpc port, so we use jessie + # use a more recent kernel from backports + kversion='4.9.0-0.bpo.6' + kernel="${kversion}-powerpc" + debsource="deb http://archive.debian.org/debian jessie main" + debsource="${debsource}\ndeb http://archive.debian.org/debian jessie-backports main" + debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unstable main" + debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unreleased main" + + # archive.debian.org Release files are expired. + echo "Acquire::Check-Valid-Until false;" | tee -a /etc/apt/apt.conf.d/10-nocheckvalid + echo "APT::Get::AllowUnauthenticated true;" | tee -a /etc/apt/apt.conf.d/10-nocheckvalid + + dropbear="dropbear" + deps=(libcrypt1:"${arch}") + ;; + powerpc64) + # there is no stable port + arch=ppc64 + # https://packages.debian.org/en/sid/linux-image-powerpc64 + kversion='5.*' + kernel="${kversion}-powerpc64" + libgcc="libgcc-s1" + debsource="deb http://ftp.ports.debian.org/debian-ports unstable main" + debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unreleased main" + # sid version of dropbear requires these dependencies + deps=(libcrypt1:"${arch}") + ;; + powerpc64le) + arch=ppc64el + kernel="${kversion}-powerpc64le" + ;; + s390x) + arch=s390x + kernel="${kversion}-s390x" + ;; + sparc64) + # there is no stable port + # https://packages.debian.org/en/sid/linux-image-sparc64 + kernel='*-sparc64' + libgcc="libgcc-s1" + debsource="deb http://ftp.ports.debian.org/debian-ports unstable main" + debsource="${debsource}\ndeb http://ftp.ports.debian.org/debian-ports unreleased main" + # sid version of dropbear requires these dependencies + deps=(libcrypt1:"${arch}") + ;; + x86_64) + arch=amd64 + kernel="${kversion}-amd64" + ;; + *) + echo "Invalid arch: ${arch}" + exit 1 + ;; + esac + + install_packages ca-certificates \ + curl \ + cpio \ + sharutils \ + gnupg + + # Download packages + mv /etc/apt/sources.list /etc/apt/sources.list.bak + echo -e "${debsource}" > /etc/apt/sources.list + + # Old ubuntu does not support --add-architecture, so we directly change multiarch file + if [ -f /etc/dpkg/dpkg.cfg.d/multiarch ]; then + cp /etc/dpkg/dpkg.cfg.d/multiarch /etc/dpkg/dpkg.cfg.d/multiarch.bak + fi + dpkg --add-architecture "${arch}" || echo "foreign-architecture ${arch}" > /etc/dpkg/dpkg.cfg.d/multiarch + + # Add Debian keys. + curl --retry 3 -sSfL 'https://ftp-master.debian.org/keys/archive-key-{7.0,8,9,10}.asc' -O + curl --retry 3 -sSfL 'https://ftp-master.debian.org/keys/archive-key-{8,9,10}-security.asc' -O + curl --retry 3 -sSfL 'https://ftp-master.debian.org/keys/release-{7,8,9,10}.asc' -O + curl --retry 3 -sSfL 'https://www.ports.debian.org/archive_{2020,2021,2022}.key' -O + + for key in *.asc *.key; do + apt-key add "${key}" + rm "${key}" + done + + # allow apt-get to retry downloads + echo 'APT::Acquire::Retries "3";' > /etc/apt/apt.conf.d/80-retries + + apt-get update + + mkdir -p "/qemu/${arch}" + chmod 777 /qemu "/qemu/${arch}" + + cd "/qemu/${arch}" + apt-get -d --no-install-recommends download \ + ${deps[@]+"${deps[@]}"} \ + "busybox:${arch}" \ + "${dropbear}:${arch}" \ + "libtommath1:${arch}" \ + "libtomcrypt1:${arch}" \ + "libgmp10:${arch}" \ + "libc6:${arch}" \ + "${libgcc}:${arch}" \ + "libstdc++6:${arch}" \ + "linux-image-${kernel}:${arch}" \ + ncurses-base \ + "zlib1g:${arch}" + cd /qemu + + # Install packages + root="root-${arch}" + mkdir -p "${root}"/{bin,etc/dropbear,root,sys,dev,proc,sbin,tmp,usr/{bin,sbin},var/log} + for deb in "${arch}"/*deb; do + dpkg -x "${deb}" "${root}"/ + done + + cp "${root}/boot/vmlinu"* kernel + + # initrd + mkdir -p "${root}/modules" + cp -v \ + "${root}/lib/modules"/*/kernel/drivers/net/net_failover.ko \ + "${root}/lib/modules"/*/kernel/drivers/net/virtio_net.ko \ + "${root}/lib/modules"/*/kernel/drivers/virtio/* \ + "${root}/lib/modules"/*/kernel/fs/netfs/netfs.ko \ + "${root}/lib/modules"/*/kernel/fs/9p/9p.ko \ + "${root}/lib/modules"/*/kernel/fs/fscache/fscache.ko \ + "${root}/lib/modules"/*/kernel/net/9p/9pnet.ko \ + "${root}/lib/modules"/*/kernel/net/9p/9pnet_virtio.ko \ + "${root}/lib/modules"/*/kernel/net/core/failover.ko \ + "${root}/modules" || true # some file may not exist + rm -rf "${root:?}/boot" + rm -rf "${root:?}/lib/modules" + + cat << 'EOF' > "${root}/etc/hosts" +127.0.0.1 localhost qemu +EOF + + cat << 'EOF' > $root/etc/hostname +qemu +EOF + + cat << 'EOF' > $root/etc/passwd +root::0:0:root:/root:/bin/sh +EOF + +cat << 'EOF' | uudecode -o $root/etc/dropbear/dropbear_rsa_host_key +begin 600 dropbear_rsa_host_key +M````!W-S:"UR+3[X=QMH,B*4$RYULV,V3X6]K:7@Q?80"#WXGGQZNFN6CZ7LTDX(F6J[\]F5<0`HEOF:Z +MX;^53`L'4I/A```!``$L:$Z*#6<^3@+O%.[-#/5H+.C'3\#QQZN[1;J>L`8I +MZ_&T'!"J'/Y+?R?55G:M^=]R*-&I3TOJYZA8@&H51ZOAF59'1_>>Z@?E4#)$ +MQU)X/RWH51ZB5KSDWJS:D'7GD(!?NAY`C'7\)I:_4)J")QBV/P"RJQGHG'%B +M1BT2LE6676>`1K,0\NIMZTKQNB(IC+88<7#8%_-=P<&6<"9LH>60TSS?3?-C +MN`T36YB/3^<(Q;`N1NT>I9EZS`BAC^-?.:,R\7EL"<4>7E=]^1]B\K9])AQU +MBM\]M;4V(S(6KH-I.4[6>9E+@\UEM.J6:[2LUEEJDG:G:+:/EVF^Y75@(S$` +M``"!`.O+KW=&*CBCHL"11&SVO4/K]$R-]7MV7,3RR)Q[X'0;6.?4JHW!3VR6 +M*FGBY--37ZD-+UV.8_+"$6PH9)(/E.\G19#G0K`LRM?JWS!58&;D0C1```` +M@0"\[@NYWSTW(?Q@:_A*1Y3/AKYO5?S=0"<2>#V-AH6W-NCSDTSRP=2D79FS +M"D?[;.)V>8'#9&I3"MU@+:2\Z%$0-MG0+J'(0>T1_C6?*C=4U0I$DI<=@D]1 +H_&DE8Y(OT%%EPG]!$H&5HX*),_D1A2\P=R.7G'`0L%YM-79Y"T">$0`` +` +end +EOF + + # dropbear complains when this file is missing + touch "${root}/var/log/lastlog" + + cat << 'EOF' > $root/init +#!/bin/busybox sh + +set -e + +/bin/busybox --install + +mount -t devtmpfs devtmpfs /dev +mount -t proc none /proc +mount -t sysfs none /sys +mkdir /dev/pts +mount -t devpts none /dev/pts/ + +# some archs does not have virtio modules +insmod /modules/failover.ko || true +insmod /modules/net_failover.ko || true +insmod /modules/virtio.ko || true +insmod /modules/virtio_ring.ko || true +insmod /modules/virtio_mmio.ko || true +insmod /modules/virtio_pci_legacy_dev.ko || true +insmod /modules/virtio_pci_modern_dev.ko || true +insmod /modules/virtio_pci.ko || true +insmod /modules/virtio_net.ko || true +insmod /modules/netfs.ko || true +insmod /modules/fscache.ko +insmod /modules/9pnet.ko +insmod /modules/9pnet_virtio.ko || true +insmod /modules/9p.ko + +ifconfig lo 127.0.0.1 +ifconfig eth0 10.0.2.15 +route add default gw 10.0.2.2 eth0 + +mkdir /target +mount -t 9p -o trans=virtio target /target -oversion=9p2000.u || true + +exec dropbear -F -E -B +EOF + + chmod +x "${root}/init" + cd "${root}" + find . | cpio --create --format='newc' --quiet | gzip > ../initrd.gz + cd - + + # Clean up + rm -rf "/qemu/${root}" "/qemu/${arch}" + mv -f /etc/apt/sources.list.bak /etc/apt/sources.list + if [ -f /etc/dpkg/dpkg.cfg.d/multiarch.bak ]; then + mv /etc/dpkg/dpkg.cfg.d/multiarch.bak /etc/dpkg/dpkg.cfg.d/multiarch + fi + # can fail if arch is used (amd64 and/or i386) + dpkg --remove-architecture "${arch}" || true + apt-get update + + purge_packages + + ls -lh /qemu +} + +main "${@}" diff --git a/.docker/cross/linux-runner b/.docker/cross/linux-runner new file mode 100755 index 000000000..2ef0efc67 --- /dev/null +++ b/.docker/cross/linux-runner @@ -0,0 +1,173 @@ +#!/usr/bin/env bash + +set -e + +LOG=/tmp/qemu.log +LOCK=/tmp/qemu.lock + +if [ -n "${CROSS_DEBUG}" ]; then + set -x +fi + +# arch in the rust target +arch="${1}" +shift + +if [ "${CROSS_RUNNER}" = "" ]; then + if [[ "${arch}" == i?86 ]] || [[ "${arch}" == x86_64 ]]; then + CROSS_RUNNER=native + else + CROSS_RUNNER=qemu-user + fi +fi + +# select qemu arch +qarch="${arch}" +case "${arch}" in + armv7) + qarch="arm" + ;; + i686) + qarch="i386" + ;; + powerpc) + qarch="ppc" + ;; + powerpc64) + qarch="ppc64" + ;; + powerpc64le) + if [ "${CROSS_RUNNER}" = "qemu-user" ]; then + qarch="ppc64le" + else + qarch="ppc64" + fi + ;; +esac + +case "${CROSS_RUNNER}" in + native) + exec "${@}" + ;; + qemu-user) + exec "qemu-${qarch}" "${@}" + ;; + qemu-system) + true + ;; + *) + echo "Invalid runner: \"${CROSS_RUNNER}\""; + echo "Valid runners are: native, qemu-user and qemu-system" + exit 1 + ;; +esac + +n="$(nproc)" +memory=1G +driver9p="virtio-9p-pci" +drivernet="virtio-net-pci" + +# select qemu parameters +case "${arch}" in + aarch64) + # 8 is the max number of cpu supported by qemu-aarch64 + n=$(( n > 8 ? 8 : n )) + opt="-machine virt -cpu cortex-a57" + ;; + armv7) + opt="-machine virt" + driver9p="virtio-9p-device" + drivernet="virtio-net-device" + ;; + i686) + opt="-append console=ttyS0" + ;; + mips|mipsel) + # avoid kernel error + # https://blahcat.github.io/2017/07/14/building-a-debian-stretch-qemu-image-for-mipsel/ + opt="-append nokaslr" + n=1 + ;; + mips64el) + # avoid kernel error + # https://blahcat.github.io/2017/07/14/building-a-debian-stretch-qemu-image-for-mipsel/ + opt="-append nokaslr -cpu MIPS64R2-generic" + n=1 + ;; + powerpc) + opt="-append console=ttyPZ0" + n=1 + ;; + powerpc64|powerpc64le) + opt="-append console=hvc0 --nodefaults -serial stdio" + ;; + s390x) + n=1 + driver9p="virtio-9p-ccw" + drivernet="virtio-net-ccw" + ;; + sparc64) + n=1 + driver9p+=",bus=pciB" + drivernet+=",bus=pciB" + ;; + x86_64) + opt="-append console=ttyS0" + ;; +esac + +( + flock -n 200 || exit 0 + + echo Booting QEMU virtual machine with $n cpus... + + QEMU_CMD="qemu-system-${qarch} \ + -m ${memory} \ + -smp ${n} \ + -nographic \ + -monitor none \ + -netdev user,id=net0,hostfwd=tcp::10022-:22 \ + -device ${drivernet},netdev=net0 \ + -kernel /qemu/kernel \ + -initrd /qemu/initrd.gz \ + ${opt} \ + -fsdev local,id=fs0,path=/target,security_model=mapped \ + -device ${driver9p},fsdev=fs0,mount_tag=target" + + touch "${LOG}" + if [[ -n "${CROSS_DEBUG}" ]]; then + (${QEMU_CMD} 2>&1 | tee -a "${LOG}") & + else + ${QEMU_CMD} >> "${LOG}" 2>&1 & + fi + + # wait for dropbear + for _ in $(seq 240); do + if grep -q "Not backgrounding" "${LOG}"; then + READY=1 + break + fi + sleep 0.5s + done + + if [ -z "${READY}" ]; then + if [ -n "${CROSS_DEBUG}" ]; then + echo "Not ready but continuing because CROSS_DEBUG is set" + else + echo "Qemu is not ready after ${SECONDS} seconds..." + echo "Set the environment variable CROSS_DEBUG=1 to debug" + echo "Last 100 lines of qemu output:" + tail -n 100 "${LOG}" + exit 1 + fi + fi + + echo "Booted in ${SECONDS} seconds" + +) 200>"${LOCK}" + +if [[ -t 1 ]] && [[ -t 2 ]]; then + tty_flag='-t' +fi + +exec dbclient ${tty_flag} -p 10022 -y -y root@localhost "${@}" diff --git a/.docker/cross/qemu.sh b/.docker/cross/qemu.sh new file mode 100755 index 000000000..75626c55c --- /dev/null +++ b/.docker/cross/qemu.sh @@ -0,0 +1,233 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +# shellcheck disable=SC1091 +. lib.sh + +build_static_libffi () { + local version=3.0.13 + + local td + td="$(mktemp -d)" + + pushd "${td}" + + + curl --retry 3 -sSfL "https://github.com/libffi/libffi/archive/refs/tags/v${version}.tar.gz" -O -L + tar --strip-components=1 -xzf "v${version}.tar.gz" + ./configure --prefix="$td"/lib --disable-builddir --disable-shared --enable-static + make "-j$(nproc)" + install -m 644 ./.libs/libffi.a /usr/lib64/ + + popd + + rm -rf "${td}" +} + +build_static_libmount () { + local version_spec=2.23.2 + local version=2.23 + local td + td="$(mktemp -d)" + + pushd "${td}" + + curl --retry 3 -sSfL "https://kernel.org/pub/linux/utils/util-linux/v${version}/util-linux-${version_spec}.tar.xz" -O -L + tar --strip-components=1 -xJf "util-linux-${version_spec}.tar.xz" + ./configure --disable-shared --enable-static --without-ncurses + make "-j$(nproc)" mount blkid + install -m 644 ./.libs/*.a /usr/lib64/ + + popd + + rm -rf "${td}" +} + + +build_static_libattr() { + local version=2.4.46 + + local td + td="$(mktemp -d)" + + pushd "${td}" + + yum install -y gettext + + curl --retry 3 -sSfL "https://download.savannah.nongnu.org/releases/attr/attr-${version}.src.tar.gz" -O + tar --strip-components=1 -xzf "attr-${version}.src.tar.gz" + cp /usr/share/automake*/config.* . + + ./configure + make "-j$(nproc)" + install -m 644 ./libattr/.libs/libattr.a /usr/lib64/ + + yum remove -y gettext + + popd + + rm -rf "${td}" +} + +build_static_libcap() { + local version=2.22 + + local td + td="$(mktemp -d)" + + pushd "${td}" + + curl --retry 3 -sSfL "https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-${version}.tar.xz" -O + tar --strip-components=1 -xJf "libcap-${version}.tar.xz" + make "-j$(nproc)" + install -m 644 libcap/libcap.a /usr/lib64/ + + popd + + rm -rf "${td}" +} + +build_static_pixman() { + local version=0.34.0 + + local td + td="$(mktemp -d)" + + pushd "${td}" + + curl --retry 3 -sSfL "https://www.cairographics.org/releases/pixman-${version}.tar.gz" -O + tar --strip-components=1 -xzf "pixman-${version}.tar.gz" + ./configure + make "-j$(nproc)" + install -m 644 ./pixman/.libs/libpixman-1.a /usr/lib64/ + + popd + + rm -rf "${td}" +} + +main() { + local version=5.1.0 + + if_centos version=4.2.1 + + local arch="${1}" \ + softmmu="${2:-}" + + install_packages \ + autoconf \ + automake \ + bison \ + bzip2 \ + curl \ + flex \ + libtool \ + make \ + patch \ + python3 \ + + if_centos install_packages \ + gcc-c++ \ + pkgconfig \ + xz \ + glib2-devel \ + glib2-static \ + glibc-static \ + libattr-devel \ + libcap-devel \ + libfdt-devel \ + pcre-static \ + pixman-devel \ + libselinux-devel \ + libselinux-static \ + libffi \ + libuuid-devel \ + libblkid-devel \ + libmount-devel \ + zlib-devel \ + zlib-static + + if_centos 'curl --retry 3 -sSfL "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD" -o /usr/share/automake*/config.guess' + if_centos 'curl --retry 3 -sSfL "https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD" -o /usr/share/automake*/config.sub' + + # these are not packaged as static libraries in centos; build them manually + if_centos build_static_libffi + if_centos build_static_libmount + if_centos build_static_libattr + if_centos build_static_libcap + if_centos build_static_pixman + + if_ubuntu install_packages \ + g++ \ + pkg-config \ + xz-utils \ + libattr1-dev \ + libcap-ng-dev \ + libffi-dev \ + libglib2.0-dev \ + libpixman-1-dev \ + libselinux1-dev \ + zlib1g-dev + + # if we have python3.6+, we can install qemu 6.1.0, which needs ninja-build + # ubuntu 16.04 only provides python3.5, so remove when we have a newer qemu. + is_ge_python36=$(python3 -c "import sys; print(int(sys.version_info >= (3, 6)))") + if [[ "${is_ge_python36}" == "1" ]]; then + if_ubuntu version=6.1.0 + if_ubuntu install_packages ninja-build + fi + + local td + td="$(mktemp -d)" + + pushd "${td}" + + curl --retry 3 -sSfL "https://download.qemu.org/qemu-${version}.tar.xz" -O + tar --strip-components=1 -xJf "qemu-${version}.tar.xz" + + local targets="${arch}-linux-user" + local virtfs="" + case "${softmmu}" in + softmmu) + if [ "${arch}" = "ppc64le" ]; then + targets="${targets},ppc64-softmmu" + else + targets="${targets},${arch}-softmmu" + fi + virtfs="--enable-virtfs" + ;; + "") + true + ;; + *) + echo "Invalid softmmu option: ${softmmu}" + exit 1 + ;; + esac + + ./configure \ + --disable-kvm \ + --disable-vnc \ + --disable-guest-agent \ + --enable-linux-user \ + --static \ + ${virtfs} \ + --target-list="${targets}" + make "-j$(nproc)" + make install + + # HACK the binfmt_misc interpreter we'll use expects the QEMU binary to be + # in /usr/bin. Create an appropriate symlink + ln -s "/usr/local/bin/qemu-${arch}" "/usr/bin/qemu-${arch}-static" + + purge_packages + + popd + + rm -rf "${td}" + rm "${0}" +} + +main "${@}" diff --git a/.docker/cross/xargo.sh b/.docker/cross/xargo.sh new file mode 100755 index 000000000..5f7e2dcd6 --- /dev/null +++ b/.docker/cross/xargo.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +set -x +set -euo pipefail + +# shellcheck disable=SC1091 +. lib.sh + +main() { + install_packages ca-certificates curl + + export RUSTUP_HOME=/tmp/rustup + export CARGO_HOME=/tmp/cargo + + curl --retry 3 -sSfL https://sh.rustup.rs -o rustup-init.sh + sh rustup-init.sh -y --no-modify-path --profile minimal + rm rustup-init.sh + + PATH="${CARGO_HOME}/bin:${PATH}" cargo install xargo --root /usr/local + + rm -r "${RUSTUP_HOME}" "${CARGO_HOME}" + + purge_packages + + rm "${0}" +} + +main "${@}" diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..e8c2a92f2 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,132 @@ +name: docker + +on: + workflow_dispatch: + #pull_request: + # paths: + # - '.docker/**' + # - '.github/workflows/docker.yml' + +jobs: + setup: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: install stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + + - name: install Linux dependencies + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev + + - name: install cross + run: cargo install cross --git https://github.com/cross-rs/cross + + - name: Upload cross + uses: actions/upload-artifact@v3 + with: + name: cross + path: '~/.cargo/bin/cross' + if-no-files-found: error + + - name: build CLI + uses: actions-rs/cargo@v1 + with: + command: build + args: --manifest-path ./tooling/cli/Cargo.toml + + - name: Upload CLI + uses: actions/upload-artifact@v3 + with: + name: cargo-tauri + path: tooling/cli/target/debug/cargo-tauri + if-no-files-found: error + + docker: + needs: setup + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + target: + - { name: 'aarch64-unknown-linux-gnu', filename: 'aarch64' } + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: install stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + target: ${{ matrix.target.name }} + + - name: Setup node + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Download cross + uses: actions/download-artifact@v3 + with: + name: cross + path: '~/.cargo/bin' + + - name: Download CLI + uses: actions/download-artifact@v3 + with: + name: cargo-tauri + path: 'examples/api' + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and export to Docker + uses: docker/build-push-action@v3 + with: + context: .docker/cross + file: .docker/cross/${{ matrix.target.filename }}.Dockerfile + load: true + tags: ${{ matrix.target.name }}:latest + + - name: install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libgtk-3-dev webkit2gtk-4.0 libayatana-appindicator3-dev librsvg2-dev patchelf + + - name: Test + run: | + cd tooling/api + yarn && yarn build + cd ../../examples/api + yarn + . .setup-cross.sh + chmod +x cargo-tauri + chmod +x $HOME/.cargo/bin/cross + ./cargo-tauri build --runner cross --bundles deb --target ${{ matrix.target.name }} --verbose + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: .docker/cross + file: .docker/cross/${{ matrix.target.filename }}.Dockerfile + push: true + tags: ghcr.io/${{ github.repository }}/${{ matrix.target.name }}:latest diff --git a/.scripts/docker/build.sh b/.scripts/docker/build.sh new file mode 100755 index 000000000..cac4ba70a --- /dev/null +++ b/.scripts/docker/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +docker build -t aarch64-unknown-linux-gnu:latest --file .docker/cross/aarch64.Dockerfile .docker/cross diff --git a/examples/api/.setup-cross.sh b/examples/api/.setup-cross.sh new file mode 100644 index 000000000..22d5ee139 --- /dev/null +++ b/examples/api/.setup-cross.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +export ICONS_VOLUME="$(realpath ../.icons)" +export DIST_VOLUME="$(realpath dist)" +export ISOLATION_VOLUME="$(realpath isolation-dist)" diff --git a/examples/api/src-tauri/Cross.toml b/examples/api/src-tauri/Cross.toml new file mode 100644 index 000000000..a957b1e33 --- /dev/null +++ b/examples/api/src-tauri/Cross.toml @@ -0,0 +1,11 @@ +[build.env] +# must set ICONS_VOLUME, DIST_VOLUME and ISOLATION_VOLUME environment variables +# ICONS_VOLUME: absolute path to the .icons folder +# DIST_VOLUME: absolute path to the dist folder +# ISOLATION_VOLUME: absolute path to the isolation dist folder +# this can be done running `$ . .setup-cross.sh` in the examples/api folder +volumes = ["ICONS_VOLUME", "DIST_VOLUME", "ISOLATION_VOLUME"] + +[target.aarch64-unknown-linux-gnu] +image = "aarch64-unknown-linux-gnu:latest" +#image = "ghcr.io/tauri-apps/tauri/aarch64-unknown-linux-gnu:latest" diff --git a/examples/api/src-tauri/tauri.conf.json b/examples/api/src-tauri/tauri.conf.json index 60419d0f2..3f3dd772e 100644 --- a/examples/api/src-tauri/tauri.conf.json +++ b/examples/api/src-tauri/tauri.conf.json @@ -8,7 +8,7 @@ }, "package": { "productName": "Tauri API", - "version": "../package.json" + "version": "1.0.0" }, "tauri": { "pattern": {