feat(runtime): native platform backends and UI vessels onto main
This commit is contained in:
Executable
+182
@@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env bash
|
||||
# build-gtk4.sh — Compile and run native-hello using the GTK4 bridge on macOS.
|
||||
#
|
||||
# Usage:
|
||||
# ./build-gtk4.sh # compile and run
|
||||
# ./build-gtk4.sh compile # compile only
|
||||
# ./build-gtk4.sh clean # remove build artefacts
|
||||
#
|
||||
# Requirements:
|
||||
# - elc in PATH (or ../../../lang/dist/platform/elc)
|
||||
# - clang (Xcode Command Line Tools)
|
||||
# - GTK4 via Homebrew: brew install gtk4
|
||||
# - macOS 12+
|
||||
#
|
||||
# This is the same pipeline as build.sh but targeting the GTK4 backend:
|
||||
# - Links with $(pkg-config --libs gtk4) instead of -framework Cocoa
|
||||
# - Compiles el_gtk4.c (plain C) instead of el_appkit.m (ObjC)
|
||||
# - Defines EL_TARGET_LINUX (the GTK4 target flag)
|
||||
#
|
||||
# Multi-file compilation strategy: see build.sh comments — identical rationale.
|
||||
|
||||
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-gtk4"
|
||||
|
||||
# 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 it at:"
|
||||
echo " ${EL_LANG_ROOT}/dist/platform/elc"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# GTK4 pkg-config flags
|
||||
GTK4_CFLAGS=$(pkg-config --cflags gtk4)
|
||||
GTK4_LIBS=$(pkg-config --libs gtk4)
|
||||
|
||||
CLANG_FLAGS_COMMON=(
|
||||
-std=c11
|
||||
-DEL_TARGET_LINUX
|
||||
-I "${EL_RUNTIME}"
|
||||
)
|
||||
|
||||
clean() {
|
||||
rm -rf "${BUILD_DIR}"
|
||||
echo "Cleaned."
|
||||
}
|
||||
|
||||
compile() {
|
||||
mkdir -p "${BUILD_DIR}"
|
||||
|
||||
# ── 1. Vessel forward-declarations header ─────────────────────────────────
|
||||
# elc --emit-header emits full function bodies, not just prototypes.
|
||||
# Extract only the forward-declaration lines: stop at the first function
|
||||
# definition (a line that ends with ') {' opening a body block).
|
||||
# macOS awk does not support \s — use POSIX [[:space:]] instead.
|
||||
echo "==> Generating el-native vessel header (declarations only)..."
|
||||
"${ELC}" --emit-header "${EL_NATIVE_VESSEL}" \
|
||||
| awk 'BEGIN{in_body=0} /^[a-zA-Z_].+\)[[:space:]]*\{/ {in_body=1} !in_body{print}' \
|
||||
> "${BUILD_DIR}/el_native_vessel.h"
|
||||
|
||||
# ── 2. Compile el-native vessel to C ──────────────────────────────────────
|
||||
echo "==> Compiling el-native vessel to C..."
|
||||
"${ELC}" "${EL_NATIVE_VESSEL}" \
|
||||
> "${BUILD_DIR}/el_native_vessel.c"
|
||||
|
||||
# ── 3. Compile app entry to C ─────────────────────────────────────────────
|
||||
echo "==> Compiling app entry to C..."
|
||||
EL_MANIFEST="${SCRIPT_DIR}/manifest.el" \
|
||||
"${ELC}" "${SCRIPT_DIR}/src/main.el" \
|
||||
> "${BUILD_DIR}/native_hello.c"
|
||||
|
||||
# ── 4. Compile el_gtk4.c (plain C, GTK4 backend) ─────────────────────────
|
||||
echo "==> Compiling el_gtk4.c (GTK4 bridge)..."
|
||||
# shellcheck disable=SC2086
|
||||
clang \
|
||||
-std=c11 \
|
||||
-DEL_TARGET_LINUX \
|
||||
-I "${EL_RUNTIME}" \
|
||||
${GTK4_CFLAGS} \
|
||||
-c "${EL_RUNTIME}/el_gtk4.c" \
|
||||
-o "${BUILD_DIR}/el_gtk4.o"
|
||||
|
||||
# ── 5a. Compile el_seed.c ─────────────────────────────────────────────────
|
||||
# el_seed.c provides the OS-boundary __-prefixed primitives + thin wrappers.
|
||||
# With -DEL_TARGET_LINUX, the EL_TARGET_LINUX section in el_seed.c is
|
||||
# compiled in (GTK4 forwarders) and the EL_TARGET_MACOS section is excluded.
|
||||
echo "==> Compiling el_seed.c (EL_TARGET_LINUX)..."
|
||||
# shellcheck disable=SC2086
|
||||
clang "${CLANG_FLAGS_COMMON[@]}" \
|
||||
${GTK4_CFLAGS} \
|
||||
-c "${EL_RUNTIME}/el_seed.c" \
|
||||
-o "${BUILD_DIR}/el_seed.o"
|
||||
|
||||
# ── 5b. Compile el_runtime.c and patch out duplicate __-prefixed symbols ──
|
||||
# Same strategy as build.sh: el_runtime.c has duplicates of the __-prefixed
|
||||
# OS wrappers that el_seed.c defines. Hide el_runtime.o's copies with nmedit.
|
||||
echo "==> Compiling el_runtime.c..."
|
||||
clang "${CLANG_FLAGS_COMMON[@]}" \
|
||||
-c "${EL_RUNTIME}/el_runtime.c" \
|
||||
-o "${BUILD_DIR}/el_runtime.o"
|
||||
|
||||
echo "==> Patching el_runtime.o (hiding __-prefixed symbols duplicated in el_seed.o)..."
|
||||
nm "${BUILD_DIR}/el_seed.o" 2>/dev/null \
|
||||
| awk '/^[0-9a-f]+ T _/{print $3}' | sort > "${BUILD_DIR}/.seed_T.txt"
|
||||
nm "${BUILD_DIR}/el_runtime.o" 2>/dev/null \
|
||||
| awk '/^[0-9a-f]+ T _/{print $3}' | sort > "${BUILD_DIR}/.rt_T.txt"
|
||||
comm -23 "${BUILD_DIR}/.rt_T.txt" "${BUILD_DIR}/.seed_T.txt" \
|
||||
> "${BUILD_DIR}/.rt_keep.txt"
|
||||
nmedit -s "${BUILD_DIR}/.rt_keep.txt" "${BUILD_DIR}/el_runtime.o"
|
||||
|
||||
# ── 6. Compile el-native vessel object ────────────────────────────────────
|
||||
# Vessel code calls __-prefixed builtins. el_native_target.h provides the
|
||||
# EL_TARGET_LINUX block of declarations (same function signatures as MACOS).
|
||||
echo "==> Compiling el-native vessel object..."
|
||||
clang "${CLANG_FLAGS_COMMON[@]}" \
|
||||
-include "${EL_RUNTIME}/el_native_target.h" \
|
||||
-c "${BUILD_DIR}/el_native_vessel.c" \
|
||||
-o "${BUILD_DIR}/el_native_vessel.o"
|
||||
|
||||
echo "==> Patching el_native_vessel.o (hiding vessel main)..."
|
||||
nm "${BUILD_DIR}/el_native_vessel.o" 2>/dev/null \
|
||||
| awk '/^[0-9a-f]+ T _/{print $3}' \
|
||||
| grep -v '^_main$' \
|
||||
> "${BUILD_DIR}/.vessel_keep.txt"
|
||||
nmedit -s "${BUILD_DIR}/.vessel_keep.txt" "${BUILD_DIR}/el_native_vessel.o"
|
||||
|
||||
# ── 7. Compile app object ─────────────────────────────────────────────────
|
||||
# Inject el_native_target.h (float ops + EL_TARGET_LINUX native decls) and
|
||||
# the vessel's forward-declaration header.
|
||||
echo "==> Compiling app object..."
|
||||
clang "${CLANG_FLAGS_COMMON[@]}" \
|
||||
-include "${EL_RUNTIME}/el_native_target.h" \
|
||||
-include "${BUILD_DIR}/el_native_vessel.h" \
|
||||
-c "${BUILD_DIR}/native_hello.c" \
|
||||
-o "${BUILD_DIR}/native_hello.o"
|
||||
|
||||
# ── 8. Link ───────────────────────────────────────────────────────────────
|
||||
# el_seed.o = OS-boundary primitives (__-prefixed) + GTK4 forwarders
|
||||
# el_runtime.o = high-level builtins (str_len, json_*, etc.), patched
|
||||
# el_native_vessel.o = el-level widget API, patched
|
||||
# el_gtk4.o = GTK4 C bridge
|
||||
# GTK4_LIBS = $(pkg-config --libs gtk4)
|
||||
# -ldl = dlsym for callback dispatch
|
||||
# -lpthread = threading
|
||||
echo "==> Linking native-hello-gtk4..."
|
||||
# shellcheck disable=SC2086
|
||||
clang "${CLANG_FLAGS_COMMON[@]}" \
|
||||
"${BUILD_DIR}/native_hello.o" \
|
||||
"${BUILD_DIR}/el_native_vessel.o" \
|
||||
"${BUILD_DIR}/el_gtk4.o" \
|
||||
"${BUILD_DIR}/el_runtime.o" \
|
||||
"${BUILD_DIR}/el_seed.o" \
|
||||
${GTK4_LIBS} \
|
||||
-ldl \
|
||||
-lpthread \
|
||||
-lcurl \
|
||||
-o "${BUILD_DIR}/native-hello-gtk4"
|
||||
|
||||
echo "==> Build complete: ${BUILD_DIR}/native-hello-gtk4"
|
||||
}
|
||||
|
||||
run() {
|
||||
compile
|
||||
echo "==> Launching native-hello-gtk4..."
|
||||
EL_MANIFEST="${SCRIPT_DIR}/manifest.el" \
|
||||
"${BUILD_DIR}/native-hello-gtk4"
|
||||
}
|
||||
|
||||
case "${1:-run}" in
|
||||
clean) clean ;;
|
||||
compile) compile ;;
|
||||
run|*) run ;;
|
||||
esac
|
||||
Reference in New Issue
Block a user