Files
el/ui/examples/native-hello/docker-build-linux.sh
T

129 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# docker-build-linux.sh — Build native-hello for Linux using Docker.
#
# Usage:
# ./docker-build-linux.sh # build ARM64 (native on Apple Silicon)
# ./docker-build-linux.sh --x86 # also build x86_64 via QEMU
# ./docker-build-linux.sh --x86-only # only build x86_64
#
# Output binaries are placed in ./build/:
# native-hello-linux-arm64 — Linux ARM64 (Raspberry Pi 3/4/5, Apple Silicon VMs)
# native-hello-linux-x86_64 — Linux x86_64 (desktop Linux, CI servers)
#
# Prerequisites:
# - Docker (Rancher Desktop / Docker Desktop)
# - elc at ../../../lang/dist/platform/elc or in PATH
#
# How it works:
# 1. elc generates C sources from the el program (macOS, ARM64 native elc)
# 2. Docker builds those C sources inside Ubuntu 22.04 + GTK4
# 3. The resulting ELF binary is extracted from the image
#
# Linux toolchain notes:
# - GNU ld rejects duplicate symbol definitions that macOS ld accepts silently.
# The Dockerfile uses objcopy --localize-symbol to hide duplicates between
# el_seed.o / el_runtime.o and el_native_vessel.o / native_hello.o.
# - el_gtk4.c requires _GNU_SOURCE for RTLD_DEFAULT (dlfcn.h).
# - G_APPLICATION_DEFAULT_FLAGS was added in GLib 2.74; Ubuntu 22.04 ships
# GLib 2.72, so the Dockerfile adds a compatibility define.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
EL_LANG_ROOT="${SCRIPT_DIR}/../../../lang"
EL_UI_ROOT="${SCRIPT_DIR}/../.."
EL_RUNTIME="${EL_LANG_ROOT}/el-compiler/runtime"
EL_NATIVE_VESSEL="${EL_UI_ROOT}/vessels/el-native/src/main.el"
BUILD_DIR="${SCRIPT_DIR}/build"
DOCKER_CTX="${SCRIPT_DIR}/build-docker"
BUILD_X86=0
BUILD_ARM64=1
for arg in "$@"; do
case "${arg}" in
--x86) BUILD_X86=1 ;;
--x86-only) BUILD_X86=1; BUILD_ARM64=0 ;;
esac
done
# ── Locate elc ────────────────────────────────────────────────────────────────
if command -v elc &>/dev/null; then
ELC="elc"
elif [ -x "${EL_LANG_ROOT}/dist/platform/elc" ]; then
ELC="${EL_LANG_ROOT}/dist/platform/elc"
else
echo "Error: elc not found. Add it to PATH or place at:"
echo " ${EL_LANG_ROOT}/dist/platform/elc"
exit 1
fi
# ── Step 1: Generate C sources ────────────────────────────────────────────────
echo "==> Generating C sources with elc..."
mkdir -p "${DOCKER_CTX}/runtime"
# App
EL_MANIFEST="${SCRIPT_DIR}/manifest.el" \
"${ELC}" "${SCRIPT_DIR}/src/main.el" > "${DOCKER_CTX}/native_hello.c"
# Vessel
"${ELC}" "${EL_NATIVE_VESSEL}" > "${DOCKER_CTX}/el_native_vessel.c"
# Vessel header (declarations only — stop before first function body)
"${ELC}" --emit-header "${EL_NATIVE_VESSEL}" \
| awk 'BEGIN{in_body=0} /^[a-zA-Z_].+\)[[:space:]]*\{/ {in_body=1} !in_body{print}' \
> "${DOCKER_CTX}/el_native_vessel.h"
# Runtime C sources
cp "${EL_RUNTIME}/el_gtk4.c" \
"${EL_RUNTIME}/el_seed.c" \
"${EL_RUNTIME}/el_seed.h" \
"${EL_RUNTIME}/el_runtime.c" \
"${EL_RUNTIME}/el_runtime.h" \
"${EL_RUNTIME}/el_native_target.h" \
"${DOCKER_CTX}/runtime/"
echo "==> C sources ready in ${DOCKER_CTX}/"
mkdir -p "${BUILD_DIR}"
# ── Step 2: Docker build (ARM64) ─────────────────────────────────────────────
if [ "${BUILD_ARM64}" -eq 1 ]; then
echo "==> Building Linux ARM64 image..."
docker build \
--platform linux/arm64 \
-f "${SCRIPT_DIR}/Dockerfile.linux-gtk4" \
--tag el-native-linux-gtk4-arm64 \
"${DOCKER_CTX}/"
echo "==> Extracting ARM64 binary..."
docker create --name el-extract-arm64 el-native-linux-gtk4-arm64
docker cp el-extract-arm64:/build/native-hello-linux "${BUILD_DIR}/native-hello-linux-arm64"
docker rm el-extract-arm64
echo "==> ARM64 binary: ${BUILD_DIR}/native-hello-linux-arm64"
file "${BUILD_DIR}/native-hello-linux-arm64"
fi
# ── Step 3: Docker build (x86_64) ────────────────────────────────────────────
if [ "${BUILD_X86}" -eq 1 ]; then
echo "==> Building Linux x86_64 image (QEMU emulation — slower)..."
docker build \
--platform linux/amd64 \
-f "${SCRIPT_DIR}/Dockerfile.linux-gtk4" \
--tag el-native-linux-gtk4-x86_64 \
"${DOCKER_CTX}/"
echo "==> Extracting x86_64 binary..."
docker create --name el-extract-x86 el-native-linux-gtk4-x86_64
docker cp el-extract-x86:/build/native-hello-linux "${BUILD_DIR}/native-hello-linux-x86_64"
docker rm el-extract-x86
echo "==> x86_64 binary: ${BUILD_DIR}/native-hello-linux-x86_64"
file "${BUILD_DIR}/native-hello-linux-x86_64"
fi
echo ""
echo "==> Done. Binaries in ${BUILD_DIR}/"
ls -lh "${BUILD_DIR}"/native-hello-linux-* 2>/dev/null || true