Skip to content

Update frun script generation to find frun.bash #5

Update frun script generation to find frun.bash

Update frun script generation to find frun.bash #5

name: Build forkrun_ring.so (multiarch) and update frun
on:
push:
paths:
- 'ring_loadables/forkrun_ring.c'
- 'ring_loadables/frun.bash'
- 'META'
- '.github/workflows/forkrun_release.yml'
workflow_dispatch:
jobs:
build:
name: Build (${{ matrix.arch }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
# x86_64: Triple Build
- arch: x86_64
platform: linux/amd64
docker_image: fedora:latest
# AArch64
- arch: aarch64
platform: linux/arm64
docker_image: fedora:latest
extra_flags: "-march=armv8-a+crc"
# PPC64LE
- arch: ppc64le
platform: linux/ppc64le
docker_image: fedora:latest
# S390X
- arch: s390x
platform: linux/s390x
docker_image: fedora:latest
# RISC-V 64
- arch: riscv64
platform: linux/riscv64
docker_image: fedorariscv/base:latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Build in Docker (${{ matrix.arch }})
run: |
mkdir -p artifacts
# 1. Define Flags in Host Shell (Clean definition)
OPT_FLAGS="-O3 -flto=auto -fno-strict-aliasing -fno-semantic-interposition -fno-math-errno -ftree-loop-im -ftree-loop-ivcanon -fPIC"
WARN_FLAGS="-DNDEBUG -Wall -Wextra"
LINK_FLAGS="-Wl,-z,relro"
INCLUDES="-I/usr/include/bash -I/usr/include/bash/include -I/usr/include/bash/builtins"
# 2. Run Docker with Env Vars
docker run --rm \
-v $PWD:/src \
-w /src \
--platform=${{ matrix.platform }} \
-e TARGET_ARCH="${{ matrix.arch }}" \
-e EXTRA_FLAGS="${{ matrix.extra_flags }}" \
-e OPT_FLAGS="$OPT_FLAGS" \
-e WARN_FLAGS="$WARN_FLAGS" \
-e LINK_FLAGS="$LINK_FLAGS" \
-e INCLUDES="$INCLUDES" \
${{ matrix.docker_image }} \
bash -c '
# --- SETUP ---
# Using @development-tools for full build environment
# Using coreutils to provide "truncate" and "od"
echo ">>> Installing dependencies..."
if command -v dnf &>/dev/null; then
dnf install -y @development-tools bash-devel git grep sed coreutils
else
apt-get update && apt-get install -y build-essential libbash-dev git grep sed coreutils
fi
# --- FIND forkrun_ring.c ---
if [[ -f "ring_loadables/forkrun_ring.c" ]]; then
FR_C_PATH="ring_loadables/forkrun_ring.c"
elif [[ -f "forkrun_ring.c" ]]; then
FR_C_PATH="forkrun_ring.c"
else
FR_C_PATH="$(find ./ -type f -name 'forkrun_ring.c' -print -quit)"
fi
{ [[ ${FR_C_PATH} ]] && [[ -f "${FR_C_PATH}" ]]; } || { echo "ERROR: could not find path to forkrun_ring.c...ABORTING!" >&2 ; exit 1; }
# --- VERSION EXTRACTION ---
FR_VERSION="unknown"
if [ -f "ring_loadables/META" ]; then
FR_VERSION=$(grep -E "^VERSION:" "ring_loadables/META" | sed -E "s/^VERSION:[ \t]*//")
elif [ -f META ]; then
FR_VERSION=$(grep -E "^VERSION:" META | sed -E "s/^VERSION:[ \t]*//")
fi
echo "Compiling Version: $FR_VERSION"
# --- COMPILATION HELPER ---
compile_target() {
local arch_name="$1"
local march_arg="$2"
local out_file="artifacts/forkrun_ring.${arch_name}.so"
echo ">>> Building $arch_name..."
# 1. Build Array of Definitions
declare -a DEFS
DEFS+=("-DSHELL")
DEFS+=("-DHAVE_CONFIG_H")
DEFS+=("-DBUILD_OS=\"Linux\"")
DEFS+=("-DBUILD_ARCH=\"$arch_name\"")
DEFS+=("-DFORKRUN_RING_VERSION=\"$FR_VERSION\"")
# Quoting magic for spaces inside flags
DEFS+=("-DCOMPILER_FLAGS=\"$OPT_FLAGS $WARN_FLAGS $LINK_FLAGS\"")
# 2. Build Full Command Array
declare -a CMD
CMD+=(gcc "$FR_C_PATH")
CMD+=($OPT_FLAGS $WARN_FLAGS $LINK_FLAGS $INCLUDES)
CMD+=("${DEFS[@]}")
CMD+=(-shared)
if [[ -n "$march_arg" ]]; then
CMD+=($march_arg)
fi
CMD+=(-o "$out_file")
# 3. Execute
"${CMD[@]}"
strip --strip-unneeded "$out_file"
# 4. Verify
enable -f "$out_file" ring_version && ring_version -a || exit 1
enable -d ring_version
}
# --- EXECUTE ---
if [ "$TARGET_ARCH" == "x86_64" ]; then
compile_target "x86-64-v2" "-march=x86-64-v2"
compile_target "x86-64-v3" "-march=x86-64-v3"
compile_target "x86-64-v4" "-march=x86-64-v4"
else
compile_target "$TARGET_ARCH" "$EXTRA_FLAGS"
fi
'
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: forkrun-libs-${{ matrix.arch }}
path: artifacts/*.so
embed:
name: Embed Base64 into frun
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: all_artifacts
- name: Flatten Artifacts
run: |
mkdir -p artifacts
find all_artifacts -name "*.so" -exec mv {} artifacts/ \;
ls -l artifacts/
- name: Extract Encoding Function
run: |
- name: Generate New frun Script
shell: bash
run: |
# find the path to frun.bash
# --- FIND frun.bash ---
if [[ -f "ring_loadables/frun.bash" ]]; then
FR_BASH_PATH="ring_loadables/frun.bash"
elif [[ -f "frun.bash" ]]; then
FR_BASH_PATH="frun.bash"
else
FR_BASH_PATH="$(find ./ -type f -name 'frun.bash' -print -quit)"
fi
{ [[ ${FR_BASH_PATH} ]] && [[ -f "${FR_BASH_PATH}" ]]; } || { echo "ERROR: could not find path to frun.bash...ABORTING!" >&2 ; exit 1; }
# Pull the helper function out of frun so we can source it
sed -n '/^_forkrun_file_to_base64() {/,/^}/p' "${FR_BASH_PATH}" > encoder.sh
# Source the helper
source encoder.sh
# Initialize buffers
a0=''
a1=''
# 1. Read frun.bash using your logic (Top Half)
{
IFS=
while true; do
read -r -u 3 a
if [[ "$a" == '_forkrun_file_to_base64() {'* ]]; then
a1+="${a}"$'\n'
break
else
a0+="${a}"$'\n'
fi
done
# Read function body (Middle)
while true; do
read -r -u 3 a
a1+="${a}"$'\n'
[[ "$a" == '# <@@@@@< _BASE64_START_ >@@@@@> #'* ]] && break
done
} 3<"${FR_BASH_PATH}"
# 2. Encode Artifacts
unset b64
declare -A b64
for f in artifacts/*.so; do
fname=$(basename "$f")
# Extract key: forkrun_ring.x86-64-v_.so -> x86-64-v_
key="${fname#forkrun_ring.}"
key="${key%.so}"
# Normalize keys to underscores (x86_64_v3)
# to match bash variable safety conventions if desired,
# matching your local script logic.
key="${key//-/_}"
[[ "$key" == "native" ]] && key="native"
echo "Encoding $key..."
b64[${key}]="$(_forkrun_file_to_base64 "$f")"
done
# 3. Reconstruct
{
printf '%s\n%s' "$a0" "$a1"
declare -p b64
printf '\n\n_forkrun_bootstrap_setup --force\n\n'
} >./frun.new
mv frun.new "${FR_BASH_PATH}"
chmod +x "${FR_BASH_PATH}"
\rm encoder.sh
- name: Verify Final Script
run: |
# Sanity check
./frun.bash ring_version -a
- name: Create Pull Request
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "build: update embedded ring loadables"
title: "🤖 Auto-Build: Update Ring Loadables"
body: |
This PR updates the embedded `forkrun_ring` binaries.
Generated by GitHub Actions Run: [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
**Architectures:**
- x86_64 (v2, v3, v4)
- aarch64, ppc64le, s390x, riscv64
branch: "auto-build/update-loadables"
delete-branch: true