From 630f956e4aef2e8f3e74ba1e5da3339ff955e02e Mon Sep 17 00:00:00 2001 From: Stephan Hradek Date: Fri, 28 Nov 2025 09:11:48 +0100 Subject: [PATCH] feat: cross compile using docker --- .gitignore | 3 ++ platform/README.md | 49 +++++++++++++++++++++++++++++++++ platform/mac/Dockerfile | 58 +++++++++++++++++++++++++++++++++++++++ platform/mac/build.sh | 35 +++++++++++++++++++++++ platform/ts431/Dockerfile | 25 +++++++++++++++++ platform/ts431/build.sh | 4 +++ 6 files changed, 174 insertions(+) create mode 100644 platform/README.md create mode 100644 platform/mac/Dockerfile create mode 100755 platform/mac/build.sh create mode 100644 platform/ts431/Dockerfile create mode 100755 platform/ts431/build.sh diff --git a/.gitignore b/.gitignore index 246b034d..0de4196b 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ result-* .vscode/ *.snap + +platform/built/ +MacOSX*.sdk* diff --git a/platform/README.md b/platform/README.md new file mode 100644 index 00000000..8283fc8d --- /dev/null +++ b/platform/README.md @@ -0,0 +1,49 @@ +# Cross Compile yazi for Different Platforms with Docker + +I do not like to have multiple different development dependencies installed on +my computer, so I usually use [Docker](https://www.docker.com) to develop and +build. + +Here are some dockerfiles to help in cross-compiling yazi for different +platforms which I use. + +- QNAP TS 431 with OS 4.3.6 +- macOS + +## Build for QNAP TS431 + +As I own a QNAP TS431, I wanted to run yazi there as well. +Unfortunately it's a quite old system so I doubt many of you will have a use for +this, but maybe it helps someone to adapt it for another, older Linux. + +To build simply run + +`platform/ts431/build.sh` + +When finished, you sholud have a directory `platform/built/ts431` containing +both, `ya` and `yazi`. + +## Build for Apple + +Here we have some options: + +- `-a` `apple`|`intel` +- `-s` *own-sdk-version* +- `-m` *minimal-target-version* + +When you have another macOS SDK than version 11.3, you can pass the version +number using `-s VERSIONNUMBER`. +Otherwise 11.3 will be downloaded and used. + +To generate an SDK tarball, follow the instructions for +[osxcross](https://github.com/tpoechtrager/osxcross?tab=readme-ov-file#packaging-the-sdk). + +Place your `MacOSX${VERSIONNMBER}.sdk.tar.xz` in`platform/mac/`. + +Running `platform/mac/build.sh` without any options, will generate executables +for Apple Silicon hardware using SDK 11.3 and targeting at least 11.0. + +To compile the same for Intel hardware run `platform/mac/build.sh -a intel`. + +The resulting `ya` and `yazi` can be found in `platform/built/mac/apple` for +Apple Silicon and `platform/built/mac/intel` for Intel hardware. diff --git a/platform/mac/Dockerfile b/platform/mac/Dockerfile new file mode 100644 index 00000000..056616d4 --- /dev/null +++ b/platform/mac/Dockerfile @@ -0,0 +1,58 @@ +ARG OWNSDK="11.3" +ARG MACMIN="11.0" +# For Apple Silicon +ARG ARCH="aarch64" +# For Intel +# ARG ARCH="x86_64" + +FROM rust:latest AS rustbuilder + +ARG OWNSDK +ARG MACMIN +ARG ARCH + +RUN apt-get update \ + && apt-get install -y --no-install-recommends build-essential ca-certificates clang cmake curl git llvm lld make pkg-config python3 xz-utils \ + && git clone --depth 1 https://github.com/tpoechtrager/osxcross.git /osxcross \ + && rm -rf /var/lib/apt/lists/* \ +; +COPY platform/mac/*.sdk.tar.xz /mac/ + +RUN if [ "$OWNSDK" = "11.3" ] ; then \ + curl -L -o /osxcross/tarballs/MacOSX11.3.sdk.tar.xz https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX11.3.sdk.tar.xz ;\ + else \ + cp /mac/MacOSX${OWNSDK}.sdk.tar.xz /osxcross/tarballs/ ;\ + fi \ + && UNATTENDED=1 OSX_VERSION_MIN=${MACMIN} /osxcross/build.sh \ + && echo rm -rf /osxcross/tarballs/* \ +; +RUN rustup target add ${ARCH}-apple-darwin \ +; + +FROM rustbuilder AS macyazi + +ARG MACMIN +ARG ARCH +ARG OWNSDK + +WORKDIR /yazi +COPY . . +RUN export PATH=/osxcross/target/bin:$PATH \ + && export SDKROOT=/osxcross/target/SDK/MacOSX${OWNSDK}.sdk \ + && export MACOSX_DEPLOYMENT_TARGET=${MACMIN} \ + && if [ "$ARCH" = "aarch64" ] ; then CSTUFF="oa64" ; else CSTUFF="o64" ; fi \ + && ARCH_KEY="${ARCH}_apple_darwin" \ + && ARCH_UPPER="$( echo "$ARCH_KEY" | tr a-z A-Z )" \ + && eval "export CC_${ARCH_KEY}=${CSTUFF}-clang" \ + && eval "export CXX_${ARCH_KEY}=${CSTUFF}-clang++" \ + && eval "export CARGO_TARGET_${ARCH_UPPER}_LINKER=${CSTUFF}-clang" \ + && eval "export AR_${ARCH_KEY}=llvm-ar" \ + && eval "export RANLIB_${ARCH_KEY}=llvm-ranlib" \ + && cargo build --locked --release --target ${ARCH}-apple-darwin \ +; + +FROM scratch + +ARG ARCH + +COPY --from=macyazi /yazi/target/${ARCH}-apple-darwin/release/ya /yazi/target/${ARCH}-apple-darwin/release/yazi / diff --git a/platform/mac/build.sh b/platform/mac/build.sh new file mode 100755 index 00000000..c7739247 --- /dev/null +++ b/platform/mac/build.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +arch="apple" +min="11.0" +sdk="11.3" +plaintext=0 +while getopts a:m:s:p opt +do + case "$opt" in + a) arch="$OPTARG" ;; + m) min="$OPTARG" ;; + s) sdk="$OPTARG" ;; + p) plaintext=1 ;; # For debugging + *) echo >&2 "unknown flag $opt" + exit 1 + ;; + esac +done + +buildargs=(--build-arg MACMIN="$min" --build-arg OWNSDK="$sdk") + +case "$arch" in + apple) buildargs+=(--build-arg ARCH="aarch64") ;; + intel) buildargs+=(--build-arg ARCH="x86_64") ;; + *) echo >&2 "unknown architecture $arch" + exit 2 + ;; +esac + +if [[ $plaintext = 1 ]] ; then + buildargs+=(--progress=plain) +fi + +dir="$( dirname "$0" )" +docker build -o "platform/built/$(basename "$dir")/$arch/" -f "$dir/Dockerfile" "${buildargs[@]}" . diff --git a/platform/ts431/Dockerfile b/platform/ts431/Dockerfile new file mode 100644 index 00000000..32f9099b --- /dev/null +++ b/platform/ts431/Dockerfile @@ -0,0 +1,25 @@ +FROM rust:slim AS builder + +# Pakete, die IMMER verfügbar sind +RUN apt-get update && apt-get install -y \ + build-essential \ + gcc-arm-linux-gnueabihf \ + pkg-config + +# Rust ARMv7 target +RUN rustup target add armv7-unknown-linux-gnueabihf + +WORKDIR /yazi +COPY . . + +# Cross-linker setzen +ENV CC=arm-linux-gnueabihf-gcc +ENV CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER=arm-linux-gnueabihf-gcc + +# wichtig für ring +ENV RUSTFLAGS="-C target-feature=+crt-static" + +RUN cargo build --release --target armv7-unknown-linux-gnueabihf + +FROM scratch +COPY --from=builder /yazi/target/armv7-unknown-linux-gnueabihf/release/yazi /yazi/target/armv7-unknown-linux-gnueabihf/release/ya / diff --git a/platform/ts431/build.sh b/platform/ts431/build.sh new file mode 100755 index 00000000..10a426f2 --- /dev/null +++ b/platform/ts431/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +dir="$( dirname "$0" )" +docker build -o "platform/built/$(basename "$dir")/" -f "$dir/Dockerfile" .