'Generic Commit'
Some checks failed
dropshell-build / build (push) Failing after 51s

This commit is contained in:
Your Name 2025-06-02 23:55:33 +12:00
parent 25fa5be7e1
commit 3fea581249
5 changed files with 32 additions and 921 deletions

View File

@ -1,49 +1,39 @@
FROM ubuntu:latest
FROM --platform=$BUILDPLATFORM alpine:latest AS builder
# Add build arguments for platform
ARG TARGETPLATFORM
ARG BUILDPLATFORM
RUN mkdir -p "$HOME/.musl-cross"
# Install build dependencies
RUN apk add --no-cache \
build-base \
cmake \
git \
musl-dev \
curl \
bash \
musl \
g++ \
ninja \
linux-headers \
mold
RUN apt-get update && apt-get install -y \
wget tar curl bash git && \
rm -rf /var/lib/apt/lists/*
# Set working directory
WORKDIR /build
RUN wget -nc -O "$HOME/.musl-cross/x86_64-linux-musl-cross.tgz" "https://getbin.xyz/x86_64-linux-musl-cross.tgz:latest" && \
tar -C "$HOME/.musl-cross" -xvf "$HOME/.musl-cross/x86_64-linux-musl-cross.tgz" && \
rm "$HOME/.musl-cross/x86_64-linux-musl-cross.tgz"
# Copy source files
COPY . .
RUN wget -nc -O "$HOME/.musl-cross/x86_64-linux-musl-native.tgz" "https://getbin.xyz/x86_64-linux-musl-native.tgz:latest" && \
tar -C "$HOME/.musl-cross" -xvf "$HOME/.musl-cross/x86_64-linux-musl-native.tgz" && \
rm "$HOME/.musl-cross/x86_64-linux-musl-native.tgz"
RUN wget -nc -O "$HOME/.musl-cross/aarch64-linux-musl-cross.tgz" "https://getbin.xyz/aarch64-linux-musl-cross.tgz:latest" && \
tar -C "$HOME/.musl-cross" -xvf "$HOME/.musl-cross/aarch64-linux-musl-cross.tgz" && \
rm "$HOME/.musl-cross/aarch64-linux-musl-cross.tgz"
RUN apt-get update && apt-get install -y \
build-essential cmake ninja-build mold nodejs npm perl jq ccache nlohmann-json3-dev \
ca-certificates upx-ucl autoconf automake libtool gawk \
&& rm -rf /var/lib/apt/lists/*
RUN install -m 0755 -d /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc && \
chmod a+r /etc/apt/keyrings/docker.asc && \
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null && \
apt-get update && \
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin && \
rm -rf /var/lib/apt/lists/*
COPY --chmod=0755 ./src/* /usr/local/bin/
RUN /usr/local/bin/dropshell-build-install-requirements
WORKDIR /app
CMD ["dropshell-build","/app"]
# Configure and build
RUN mkdir -p build_static && \
cmake -G Ninja -B build_static -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_EXE_LINKER_FLAGS="-static" \
-DCMAKE_FIND_LIBRARY_SUFFIXES=".a" \
-DBUILD_SHARED_LIBS=OFF \
${CMAKE_TOOLCHAIN_FILE:+-DCMAKE_TOOLCHAIN_FILE=$CMAKE_TOOLCHAIN_FILE}
RUN cmake --build build_static
# Final stage that only contains the binary
FROM scratch AS $PROJECT
COPY --from=builder /build/build_static/$PROJECT /$PROJECT

View File

@ -64,52 +64,10 @@ target_include_directories(${PROJECT_EXE_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure libassert
include(FetchContent)
FetchContent_Declare(
libassert
GIT_REPOSITORY https://github.com/jeremy-rifkin/libassert.git
GIT_TAG v2.1.5
)
FetchContent_MakeAvailable(libassert)
# Add cpptrace
FetchContent_Declare(
cpptrace
GIT_REPOSITORY https://github.com/jeremy-rifkin/cpptrace.git
GIT_TAG v0.8.3
)
# Explicitly configure cpptrace to use libunwind
set(CPPTRACE_UNWIND_WITH_LIBUNWIND ON CACHE BOOL "Use libunwind for unwinding" FORCE)
set(CPPTRACE_UNWIND_WITH_UNWIND OFF CACHE BOOL "Disable libgcc unwind" FORCE)
set(CPPTRACE_UNWIND_WITH_EXECINFO OFF CACHE BOOL "Disable execinfo" FORCE)
set(CPPTRACE_UNWIND_WITH_WINAPI OFF CACHE BOOL "Disable winapi" FORCE)
set(CPPTRACE_UNWIND_WITH_DBGHELP OFF CACHE BOOL "Disable dbghelp" FORCE)
set(CPPTRACE_UNWIND_WITH_NOTHING OFF CACHE BOOL "Disable nothing backend" FORCE)
# Disable cpptrace auto-configuration
set(CPPTRACE_NO_AUTO_CONFIG ON CACHE BOOL "Disable cpptrace auto-configuration" FORCE)
# Explicitly set libunwind paths
set(LibUnwind_INCLUDE_DIR "${CMAKE_SYSROOT}/usr/include" CACHE PATH "libunwind include directory" FORCE)
set(LibUnwind_LIBRARY "${CMAKE_SYSROOT}/usr/lib/libunwind.a" CACHE FILEPATH "libunwind library" FORCE)
set(LibUnwind_FOUND TRUE CACHE BOOL "libunwind found" FORCE)
FetchContent_MakeAvailable(cpptrace)
# Add nlohmann/json
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
)
FetchContent_MakeAvailable(nlohmann_json)
# Link libraries
target_link_libraries(${PROJECT_EXE_NAME} PRIVATE
libassert::assert
cpptrace::cpptrace
"${CMAKE_SYSROOT}/usr/lib/libunwind.a"
nlohmann_json::nlohmann_json
)

View File

@ -1,22 +0,0 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
# download the sos binary
SOS="${SCRIPT_DIR}/temp/sos"
mkdir -p "${SCRIPT_DIR}/temp"
curl -L -o "${SOS}" https://getbin.xyz/sos
chmod +x "${SOS}"
# upload the dropshell-build script
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/src/dropshell-build" "dropshell-build:latest"
# upload the install requirements script
"${SOS}" upload "getbin.xyz" "${SCRIPT_DIR}/src/dropshell-build-install-requirements" "dropshell-build-install-requirements:latest"
# clean up
rm -rf "${SCRIPT_DIR}/temp"
echo "Done"

View File

@ -1,367 +0,0 @@
#!/bin/bash
set -euo pipefail
# SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
HOSTARCH=$(uname -m)
# set flags from command line
RELEASE=0
MULTIBUILD=0
MUSL_ROOT_PATH="${HOME}/.musl-cross"
function help() {
echo "Usage: $0 [options]"
echo "Options:"
echo " version Show version information and exit"
echo " "
echo " <directory> Build the project using cmake in <directory>"
echo " -r, --release Build release version"
echo " -m, --multi Build for multiple architectures"
}
function version() {
echo "2025.0531.0942"
}
function die() {
echo "Error: $*"
exit 1
}
function centerlittletitle() {
local TITLE="$1"
local WIDTH
# Try tput cols, then stty size, else default to 80
if command -v tput &> /dev/null; then
WIDTH=$(tput cols 2>/dev/null)
elif command -v stty &> /dev/null && [ -t 1 ]; then
WIDTH=$(stty size 2>/dev/null | awk '{print $2}')
fi
# Fallback to 80 if WIDTH is empty or not a number
if ! [[ "$WIDTH" =~ ^[0-9]+$ ]]; then
WIDTH=80
fi
local SPACES=$(( (WIDTH - ${#TITLE}) / 2 ))
printf '%*s\n' "$WIDTH" '' | tr ' ' '-'
printf "%*s%s\n" "$SPACES" "" "$TITLE"
printf '%*s\n' "$WIDTH" '' | tr ' ' '-'
}
function set_current_arch() {
export FULLARCH="$1"
# e.g. aarch64-linux-musl-cross
# ARCH=aarch64
# ARCH_OS=linux-musl-cross
# FULLARCH=aarch64-linux-musl-cross
# ARCH_SHORT_PREFIX=aarch64-linux-musl
# MUSL_PATH=/home/jde/.musl-cr oss/aarch64-linux-musl-cross
# arch should just be x86_64 or aarch64
[ -n "$FULLARCH" ] || _die "No toolchain provided"
export ARCH="${FULLARCH%%-*}"
export ARCH_OS="${FULLARCH#*-}"
export ARCH_SHORT_PREFIX="${FULLARCH%-*}"
export ARCH_MUSL_PATH="${MUSL_ROOT_PATH}/${FULLARCH}"
export ARCH_SYSROOT="${ARCH_MUSL_PATH}/${ARCH_SHORT_PREFIX}/sysroot"
export LIBPATH="$ARCH_SYSROOT/usr/lib"
[ -d "$LIBPATH" ] || export LIBPATH="$ARCH_SYSROOT/usr/lib64"
JOBS=$(nproc) # Set JOBS to the number of available CPU cores
echo "ARCH: ${ARCH}"
echo "ARCH_OS: ${ARCH_OS}"
echo "ARCH_SHORT_PREFIX: ${ARCH_SHORT_PREFIX}"
echo "ARCH_MUSL_PATH: ${ARCH_MUSL_PATH}"
echo "ARCH_SYSROOT: ${ARCH_SYSROOT}"
echo "LIBPATH: ${LIBPATH}"
# Set cross-compiler and sysroot
export CC="$ARCH_MUSL_PATH/bin/${ARCH_SHORT_PREFIX}-gcc"
[ -f "$CC" ] || export CC="$ARCH_MUSL_PATH/bin/gcc"
export CXX="${ARCH_MUSL_PATH}/bin/${ARCH_SHORT_PREFIX}-g++"
[ -f "$CXX" ] || export CXX="$ARCH_MUSL_PATH/bin/g++"
export AR="$ARCH_MUSL_PATH/bin/${ARCH_SHORT_PREFIX}-ar"
[ -f "$AR" ] || export AR="$ARCH_MUSL_PATH/bin/ar"
export RANLIB="$ARCH_MUSL_PATH/bin/${ARCH_SHORT_PREFIX}-ranlib"
[ -f "$RANLIB" ] || export RANLIB="$ARCH_MUSL_PATH/bin/ranlib"
echo "CC: ${CC}"
echo "CXX: ${CXX}"
echo "AR: ${AR}"
echo "RANLIB: ${RANLIB}"
export CFLAGS="--sysroot=$ARCH_SYSROOT -I$ARCH_SYSROOT/usr/include"
export CXXFLAGS="--sysroot=$ARCH_SYSROOT -I$ARCH_SYSROOT/usr/include"
export CMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold"
export CMAKE_MODULE_LINKER_FLAGS="-fuse-ld=mold"
export CMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold"
export LDFLAGS="--sysroot=$ARCH_SYSROOT"
export MAKEFLAGS="-j${JOBS}"
}
OLD_PWD="$PWD"
trap 'cd "${OLD_PWD}"' EXIT
# ----------------------------------------------------------------------------------------------------------
# BUILD
# ----------------------------------------------------------------------------------------------------------
# function create_openssl_cmake_vars() {
# mkdir -p "$1/cmake/OpenSSL"
# cat <<EOF > "$1/cmake/OpenSSL/OpenSSLConfig.cmake"
# add_library(OpenSSL::SSL STATIC IMPORTED)
# set_target_properties(OpenSSL::SSL PROPERTIES
# IMPORTED_LOCATION "${OPENSSL_LIBDIR}/libssl.a"
# INTERFACE_INCLUDE_DIRECTORIES "${ARCH_SYSROOT}/usr/include"
# )
# add_library(OpenSSL::Crypto STATIC IMPORTED)
# set_target_properties(OpenSSL::Crypto PROPERTIES
# IMPORTED_LOCATION "${OPENSSL_LIBDIR}/libcrypto.a"
# INTERFACE_INCLUDE_DIRECTORIES "${ARCH_SYSROOT}/usr/include"
# )
# EOF
# }
function build_arch() {
local CMAKE_DIR="$1"
local ARCH_BUILD_DIR="${CMAKE_DIR}/build/build.$ARCH"
local OUTPUT_DIR="${CMAKE_DIR}/output"
cd "${CMAKE_DIR}" || exit 1
mkdir -p "${ARCH_BUILD_DIR}"
echo "Building for ${ARCH} in ${ARCH_BUILD_DIR}"
if [ ! -f "${ARCH_MUSL_PATH}/bin/${ARCH_SHORT_PREFIX}-g++" ]; then
echo "Musl cross toolchain not found for ${ARCH}"
echo "Missing file: ${ARCH_MUSL_PATH}/bin/${ARCH_SHORT_PREFIX}-g++"
exit 1
fi
CMAKE_BUILD_TYPE="Release"
if [ "$RELEASE" -eq 0 ]; then
CMAKE_BUILD_TYPE="Debug"
fi
export SYSROOT="${ARCH_SYSROOT}"
export OPENSSL_ROOT_DIR="${SYSROOT}/usr"
export CCACHE_DIR="${ARCH_BUILD_DIR}/ccache"
# if [ -d "${ARCH_SYSROOT}/usr/lib64" ]; then
# export OPENSSL_LIBDIR="${ARCH_SYSROOT}/usr/lib64"
# elif [ -d "${ARCH_SYSROOT}/usr/lib" ]; then
# export OPENSSL_LIBDIR="${ARCH_SYSROOT}/usr/lib"
# else
# echo "Neither lib nor lib64 found in ${ARCH_SYSROOT}/usr"
# exit 1
# fi
#create_openssl_cmake_vars "$OPENSSL_LIBDIR"
ls -la "${ARCH_SYSROOT}/usr/include/libunwind.h"
ls -la "${ARCH_SYSROOT}/usr/lib/libunwind.a"
cmake -B "${ARCH_BUILD_DIR}" -G Ninja \
-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}" \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_LINKER=mold \
-DCMAKE_C_COMPILER_TARGET="${ARCH_SHORT_PREFIX}" \
-DCMAKE_CXX_COMPILER_TARGET="${ARCH_SHORT_PREFIX}" \
-DCMAKE_C_FLAGS="${CFLAGS}" \
-DCMAKE_CXX_FLAGS="${CXXFLAGS}" \
-DCMAKE_FIND_ROOT_PATH="${ARCH_SYSROOT}" \
-DCMAKE_SYSROOT="${ARCH_SYSROOT}" \
-DCMAKE_PREFIX_PATH="${ARCH_SYSROOT}/usr" \
-DCMAKE_LIBRARY_PATH="${ARCH_SYSROOT}/usr/lib" \
-DCMAKE_LIBRARY_PATH="${ARCH_SYSROOT}/usr/lib64" \
-DCMAKE_INCLUDE_PATH="${ARCH_SYSROOT}/usr/include" \
-DCPPTRACE_STATIC_DEFINE="true"
cd "${ARCH_BUILD_DIR}" || exit 1
ninja -k0 -j"${JOBS}"
# the rest is optional.
# loop through the build directory and find executables
for executable in "${ARCH_BUILD_DIR}"/*; do
if [ -f "$executable" ] && [ -x "$executable" ]; then
local TARGET_NAME="${executable##*/}"
local TARGET_PATH="${OUTPUT_DIR}/${TARGET_NAME}.${ARCH}"
mkdir -p "${OUTPUT_DIR}"
cp "${executable}" "${TARGET_PATH}"
if command -v upx &> /dev/null ; then
echo "Compressing $TARGET_PATH with upx"
upx "${TARGET_PATH}"
fi
centerlittletitle "Built $TARGET_PATH"
fi
done
}
function build() {
echo "Building project in directory $1"
if [ ! -d "$1" ]; then
echo "Directory $1 does not exist"
exit 1
fi
local CMAKE_DIR="$1"
# if have the -m option, then build for multiple architectures
if [ $MULTIBUILD -eq 1 ]; then
echo "Building for multiple architectures"
# get all the architectures from the musl-cross-make directory
local musl_toolchains
mapfile -t musl_toolchains < <(ls -d "${MUSL_ROOT_PATH}/"*)
for tchain in "${musl_toolchains[@]}"; do
local arch="${tchain##*/}"
local buildthis="false"
if [[ "$arch" = "$HOSTARCH"* && "$arch" == *-native ]]; then
# Native toolchain for host arch
buildthis="true"
elif [[ "$arch" != "$HOSTARCH"* && "$arch" != *-native ]]; then
# Cross toolchain for non-host arch
buildthis="true"
fi
if [ "$buildthis" = "true" ]; then
echo "Building for toolchain $arch from $tchain"
set_current_arch "$arch"
build_arch "$CMAKE_DIR"
else
echo "Skipping $tchain"
fi
done
else
echo "Building for host architecture $HOSTARCH"
set_current_arch "$HOSTARCH-linux-musl-native"
build_arch "$CMAKE_DIR"
fi
}
function buildspawn() {
local CMAKE_DIR="${1:-}"
[ -n "${CMAKE_DIR:-}" ] || die "No CMake Directory given!"
[ -d "$CMAKE_DIR" ] || die "CMake Directory doesn't exist: $CMAKE_DIR"
# make canonical
CMAKE_DIR=$(realpath "$CMAKE_DIR")
FLAGS=""
[ $MULTIBUILD -eq 0 ] || FLAGS="$FLAGS -m"
[ $RELEASE -eq 0 ] || FLAGS="$FLAGS -r"
BUILD_VERSION_FILE="$HOME/.config/dropshell-build/version"
if [ ! -f "$BUILD_VERSION_FILE" ]; then
# check if docker is installed
if ! command -v docker &> /dev/null; then
echo "Neither dropshell-build nor docker appears to be available. Please install one of them."
exit 1
fi
echo "Using Docker Buildchain."
TAG="latest"
if [ -n "${DROPSHELL_BUILD_TAG-}" ]; then
TAG="$DROPSHELL_BUILD_TAG"
fi
echo "Using Docker Buildchain with tag: $TAG"
# Check if we're running in Gitea Actions
if [ -n "${JOB_CONTAINER_NAME:-}" ] && [ -n "${GITHUB_WORKSPACE:-}" ]; then
echo "--------------------------------"
echo "Running in Gitea Actions - using --volumes-from"
echo "--------------------------------"
echo "GITHUB_WORKSPACE: ${GITHUB_WORKSPACE}"
echo "CMAKE_DIR: ${CMAKE_DIR}"
echo "PWD: ${PWD}"
echo "JOB_CONTAINER_NAME: ${JOB_CONTAINER_NAME}"
docker run --rm \
--volumes-from="${JOB_CONTAINER_NAME}" \
"gitea.jde.nz/public/dropshell-build:${TAG}" \
bash -c "cd / && rm -rf /app && \
ln -s ${CMAKE_DIR} /app && \
cd /app && \
dropshell-build $FLAGS /app"
else
echo "Running locally"
docker run --rm \
-u "$(id -u)":"$(id -g)" \
-v "$CMAKE_DIR":/app \
"gitea.jde.nz/public/dropshell-build:${TAG}" \
bash -c "dropshell-build $FLAGS /app"
fi
else
echo "Using local native buildchain"
# shellcheck disable=SC2086
build "$CMAKE_DIR"
fi
}
# ----------------------------------------------------------------------------------------------------------
# MAIN
# ----------------------------------------------------------------------------------------------------------
function main() {
# Process arguments manually to support long options
while [[ $# -gt 0 ]]; do
case $1 in
-r|--release)
RELEASE=1
shift
;;
-m|--multi)
MULTIBUILD=1
shift
;;
-*)
echo "Unknown option: $1"
help
exit 1
;;
*)
# This is not an option, so break from the loop
break
;;
esac
done
# check we have at least one argument remaining
if [ $# -eq 0 ]; then
help
exit 1
fi
# get command argument, now that the flags are set
CMD="$1"
if [ -z "$CMD" ]; then
help
exit 1
fi
case "$CMD" in
version)
version
;;
*)
buildspawn "$1"
;;
esac
}
main "$@"

View File

@ -1,448 +0,0 @@
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
# list of toolchains to install
TOOLCHAIN_LIST=(
"aarch64-linux-musl-cross"
"x86_64-linux-musl-cross"
"x86_64-linux-musl-native"
)
# If the user is not root, use sudo
SUDOCMD=""
[ "$EUID" -eq 0 ] || SUDOCMD="sudo"
# If the user is not root, use the home directory of the user who ran the script
USER_HOME="$HOME"
if [ -n "${SUDO_USER:-}" ] && [ "$SUDO_USER" != "root" ]; then
USER_HOME=$(eval echo "~${SUDO_USER}")
fi
# test sudo is working or we're root (return non-zero if not root!)
if ! ${SUDOCMD:-} true; then
echo "Error: This script must be run as root or with sudo privileges." >&2
exit 1
fi
_die() {
echo -e "Error: $1" >&2
exit 1
}
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Function to print status messages
print_status() {
echo -e "${GREEN}[*] $1${NC}"
}
print_error() {
echo -e "${RED}[!] $1${NC}"
}
print_warning() {
echo -e "${YELLOW}[!] $1${NC}"
}
#----------------------------------------------------------------------------------------------------------
# Headers on Host (Native)
#----------------------------------------------------------------------------------------------------------
# Function to check if a package is installed
is_package_installed() {
if [ "$OS" = "Alpine Linux" ]; then
apk info | grep -q "^$1$"
else
dpkg -l "$1"
fi
}
function check_packages() {
local PACKAGES
# Detect distribution
if [ -f /etc/os-release ]; then
. /etc/os-release
OS=$NAME
VER=$VERSION_ID
else
print_error "Could not detect distribution"
exit 1
fi
print_status "Detected OS: $OS $VER"
# Define packages based on distribution
case $OS in
"Ubuntu")
# Common packages for both Ubuntu and Debian
PACKAGES="build-essential cmake git wget tar curl ninja-build \
mold nodejs npm perl jq ccache upx-ucl nlohmann-json3-dev \
sed gawk autoconf automake libtool autotools-dev"
;;
*)
print_error "Unsupported distribution: $OS"
exit 1
;;
esac
# Install missing packages
print_status "Checking and installing required packages..."
for pkg in $PACKAGES; do
if ! is_package_installed "$pkg"; then
print_error "Package $pkg is not installed"
exit 1
else
print_status "$pkg is already installed"
fi
done
}
# function install_libassert() {
# # put libassert headers on the host.
# echo "Checking for libassert headers"
# if [ ! -f "/usr/local/lib/libassert.a" ]; then
# echo "libassert not found, installing..."
# git clone https://github.com/jeremy-rifkin/libassert.git
# #git checkout v2.1.5
# mkdir libassert/build
# cd "libassert/build" || exit 1
# cmake .. -DCMAKE_BUILD_TYPE=Release
# make -j
# ${SUDOCMD:-} make install
# cd ../..
# rm -rf libassert
# else
# echo "libassert headers already installed"
# fi
# }
#----------------------------------------------------------------------------------------------------------
# set_current_arch
#----------------------------------------------------------------------------------------------------------
function set_current_arch() {
export FULLARCH="$1"
# e.g. aarch64-linux-musl-cross
# ARCH=aarch64
# ARCH_OS=linux-musl-cross
# FULLARCH=aarch64-linux-musl-cross
# ARCH_SHORT_PREFIX=aarch64-linux-musl
# MUSL_PATH=/home/jde/.musl-cr oss/aarch64-linux-musl-cross
# arch should just be x86_64 or aarch64
[ -n "$FULLARCH" ] || _die "No toolchain provided"
export MUSL_ROOT_PATH="${USER_HOME}/.musl-cross"
export ARCH="${FULLARCH%%-*}"
export ARCH_OS="${FULLARCH#*-}"
export ARCH_SHORT_PREFIX="${FULLARCH%-*}"
export ARCH_MUSL_PATH="${MUSL_ROOT_PATH}/${FULLARCH}"
export ARCH_SYSROOT="${ARCH_MUSL_PATH}/${ARCH_SHORT_PREFIX}/sysroot"
export LIBPATH="$ARCH_SYSROOT/usr/lib"
[ -d "$LIBPATH" ] || export LIBPATH="$ARCH_SYSROOT/usr/lib64"
echo "ARCH: ${ARCH}"
echo "ARCH_OS: ${ARCH_OS}"
echo "ARCH_SHORT_PREFIX: ${ARCH_SHORT_PREFIX}"
echo "ARCH_MUSL_PATH: ${ARCH_MUSL_PATH}"
echo "ARCH_SYSROOT: ${ARCH_SYSROOT}"
echo "LIBPATH: ${LIBPATH}"
JOBS=$(nproc) # Set JOBS to the number of available CPU cores
# Set cross-compiler and sysroot
export CC="$ARCH_MUSL_PATH/bin/${ARCH_SHORT_PREFIX}-gcc"
[ -f "$CC" ] || export CC="$ARCH_MUSL_PATH/bin/gcc"
export CXX="${ARCH_MUSL_PATH}/bin/${ARCH_SHORT_PREFIX}-g++"
[ -f "$CXX" ] || export CXX="$ARCH_MUSL_PATH/bin/g++"
export AR="$ARCH_MUSL_PATH/bin/${ARCH_SHORT_PREFIX}-ar"
[ -f "$AR" ] || export AR="$ARCH_MUSL_PATH/bin/ar"
export RANLIB="$ARCH_MUSL_PATH/bin/${ARCH_SHORT_PREFIX}-ranlib"
[ -f "$RANLIB" ] || export RANLIB="$ARCH_MUSL_PATH/bin/ranlib"
echo "CC: ${CC}"
echo "CXX: ${CXX}"
echo "AR: ${AR}"
echo "RANLIB: ${RANLIB}"
export CFLAGS="--sysroot=$ARCH_SYSROOT -I$ARCH_SYSROOT/usr/include"
export CXXFLAGS="--sysroot=$ARCH_SYSROOT -I$ARCH_SYSROOT/usr/include"
export CMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold"
export CMAKE_MODULE_LINKER_FLAGS="-fuse-ld=mold"
export CMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold"
export LDFLAGS="--sysroot=$ARCH_SYSROOT"
export MAKEFLAGS="-j${JOBS}"
}
#----------------------------------------------------------------------------------------------------------
# unwind for musl cross toolchains
#----------------------------------------------------------------------------------------------------------
function install_unwind_musl() {
set_current_arch "$1"
[ -d "$ARCH_MUSL_PATH" ] || _die "MUSL_PATH does not exist: $ARCH_MUSL_PATH"
local BUILD_DIR="${SCRIPT_DIR}/build.$ARCH"
PREVDIR="$PWD"
rm -rf "$BUILD_DIR" && mkdir -p "$BUILD_DIR" && cd "$BUILD_DIR"
[ ! -f "$LIBPATH/libunwind.a" ] || echo "Unwind $ARCH is already installed" && return
git clone https://github.com/libunwind/libunwind.git
cd libunwind
autoreconf -i
# Configure for cross-compiling
CC="$CC" AR="$AR" RANLIB="$RANLIB" ./configure \
--host="$ARCH_SHORT_PREFIX" \
--prefix="$ARCH_SYSROOT/usr" \
--enable-static \
--disable-shared \
--disable-minidebuginfo \
--disable-zlibdebuginfo
make -j"$JOBS"
${SUDOCMD:-} make install
cd "$PREVDIR"
rm -rf "$BUILD_DIR"
}
#----------------------------------------------------------------------------------------------------------
# libassert for musl cross toolchains
#----------------------------------------------------------------------------------------------------------
function install_libassert_musl() {
local TOOLCHAIN="$1"
set_current_arch "$TOOLCHAIN"
echo "Installing libassert for ${ARCH}"
local BUILD_DIR="/tmp/libassert-build-${ARCH}"
rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}"
pushd "${BUILD_DIR}"
git clone --depth 1 --branch v2.1.5 https://github.com/jeremy-rifkin/libassert.git .
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSROOT="${ARCH_SYSROOT}" \
-DCMAKE_C_COMPILER="${CC}" \
-DCMAKE_CXX_COMPILER="${CXX}" \
-DCMAKE_INSTALL_PREFIX="${ARCH_SYSROOT}/usr" \
-DBUILD_SHARED_LIBS=OFF
make
make install
popd
rm -rf "${BUILD_DIR}"
}
#----------------------------------------------------------------------------------------------------------
# cpptrace for musl cross toolchains
#----------------------------------------------------------------------------------------------------------
function install_cpptrace_musl() {
local TOOLCHAIN="$1"
set_current_arch "$TOOLCHAIN"
echo "Installing cpptrace for ${ARCH}"
local BUILD_DIR="/tmp/cpptrace-build-${ARCH}"
rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}"
pushd "${BUILD_DIR}"
git clone --depth 1 --branch v0.8.3 https://github.com/jeremy-rifkin/cpptrace.git .
mkdir build && cd build
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSROOT="${ARCH_SYSROOT}" \
-DCMAKE_C_COMPILER="${CC}" \
-DCMAKE_CXX_COMPILER="${CXX}" \
-DCMAKE_INSTALL_PREFIX="${ARCH_SYSROOT}/usr" \
-DCPPTRACE_UNWIND_WITH_LIBUNWIND=ON \
-DCPPTRACE_UNWIND_WITH_UNWIND=OFF \
-DCPPTRACE_UNWIND_WITH_EXECINFO=OFF \
-DCPPTRACE_UNWIND_WITH_WINAPI=OFF \
-DCPPTRACE_UNWIND_WITH_DBGHELP=OFF \
-DCPPTRACE_UNWIND_WITH_NOTHING=OFF \
-DCPPTRACE_NO_AUTO_CONFIG=ON \
-DLibUnwind_INCLUDE_DIR="${ARCH_SYSROOT}/usr/include" \
-DLibUnwind_LIBRARY="${ARCH_SYSROOT}/usr/lib/libunwind.a" \
-DLibUnwind_FOUND=TRUE \
-DBUILD_SHARED_LIBS=OFF \
-DCPPTRACE_STATIC_DEFINE=ON
make -j$(nproc)
make install
popd
rm -rf "${BUILD_DIR}"
}
#----------------------------------------------------------------------------------------------------------
# OpenSSL for musl cross toolchains
#----------------------------------------------------------------------------------------------------------
toolchain_to_openssl_target() {
case "$1" in
aarch64-linux-musl-*) echo "linux-aarch64" ;;
x86_64-linux-musl-*) echo "linux-x86_64" ;;
*) _die "unsupported toolchain: $1" ;;
esac
}
function install_openssl_musl() {
OPENSSL_VERSION=3.5.0
set_current_arch "${1:-}"
PREVDIR="$PWD"
[ -d "$ARCH_MUSL_PATH" ] || _die "MUSL_PATH does not exist: $ARCH_MUSL_PATH"
[ ! -f "$LIBPATH/libssl.a" ] || echo "OpenSSL $ARCH is already installed" && return
local BUILD_DIR="${SCRIPT_DIR}/build.$ARCH"
rm -rf "$BUILD_DIR" && mkdir -p "$BUILD_DIR" && cd "$BUILD_DIR"
# Helper: compare versions (returns 0 if $1 >= $2)
version_ge() {
[ "$1" = "$2" ] && return 0
[ "$(printf '%s\n' "$1" "$2" | sort -V | head -n1)" = "$2" ]
}
echo "==============================="
echo "Checking OpenSSL for $ARCH..."
echo "==============================="
OPENSSL_TARGET=$(toolchain_to_openssl_target "$FULLARCH")
wget "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" || _die "Failed to download openssl-${OPENSSL_VERSION}.tar.gz"
tar xf "openssl-${OPENSSL_VERSION}.tar.gz" || _die "Failed to extract openssl-${OPENSSL_VERSION}.tar.gz"
cd "openssl-${OPENSSL_VERSION}" || _die "Failed to cd to openssl-${OPENSSL_VERSION}"
echo "----------------------------------------------"
echo "Configuring for $ARCH with sysroot $SYSROOT..."
CC="$CC" AR="$AR" RANLIB="$RANLIB" ./Configure "$OPENSSL_TARGET" no-shared --prefix="$SYSROOT/usr"
echo "Building..."
make -j"$JOBS"
echo "Installing to $SYSROOT/usr ..."
${SUDOCMD:-} make install_sw
echo "Done for $ARCH."
echo
cd "$PREVDIR"
rm -rf "$BUILD_DIR"
echo "OpenSSL built and installed for $FULLARCH"
}
# ----------------------------------------------------------------------------------------------------------
# MUSL CROSS COMPILERS
# ----------------------------------------------------------------------------------------------------------
function check_path() {
local BASHRC="${USER_HOME}/.bashrc"
local TOOLCHAIN="$1"
local MUSL_PATH="$INSTALL_DIR/$TOOLCHAIN/bin"
if ! echo "$PATH" | grep -q "$MUSL_PATH"; then
echo "Adding $MUSL_PATH to PATH in $BASHRC"
PATH_LINE="export PATH=\"$MUSL_PATH:\$PATH\""
if ! grep -Fxq "$PATH_LINE" "$BASHRC"; then
echo "" >> "$BASHRC"
echo "# Add musl cross compilers to PATH for dropshell" >> "$BASHRC"
echo "$PATH_LINE" >> "$BASHRC"
echo "Added musl cross compilers to $BASHRC"
echo "You should run 'source ~/.bashrc' to update your PATH"
else
echo "You should run 'source ~/.bashrc' to update your PATH"
fi
fi
}
function install_musl_cross() {
local TOOLCHAIN="$1"
local MUSL_CC_URL="https://getbin.xyz"
if [ ! -d "$INSTALL_DIR/$TOOLCHAIN" ]; then
echo "Downloading $TOOLCHAIN musl cross toolchain..."
wget -nc -O "$TMPDIR/$TOOLCHAIN.tgz" "$MUSL_CC_URL/$TOOLCHAIN.tgz:latest"
tar -C "$INSTALL_DIR" -xvf "$TMPDIR/$TOOLCHAIN.tgz"
else
echo "$TOOLCHAIN musl cross toolchain already installed"
fi
}
function install_musl() {
echo "Installing musl toolchain"
# Set install directory
INSTALL_DIR="$USER_HOME/.musl-cross"
mkdir -p "$INSTALL_DIR"
TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT
for TOOLCHAIN in "${TOOLCHAIN_LIST[@]}"; do
install_musl_cross "$TOOLCHAIN"
check_path "$TOOLCHAIN"
install_openssl_musl "$TOOLCHAIN"
install_unwind_musl "$TOOLCHAIN"
install_libassert_musl "$TOOLCHAIN"
install_cpptrace_musl "$TOOLCHAIN"
done
# Clean up
rm -rf "$TMPDIR"
}
function output_version() {
local VERSIONDATE
local CONFIG_DIR="$USER_HOME/.config/dropshell-build/"
mkdir -p "$CONFIG_DIR"
VERSIONDATE="$(date +%Y.%m%d.%H%M)"
echo "$VERSIONDATE" > "$CONFIG_DIR/version" || echo "Error: Failed to write version file to $CONFIG_DIR/version"
}
#----------------------------------------------------------------------------------------------------------
# Main
#----------------------------------------------------------------------------------------------------------
function main() {
check_packages
install_musl
output_version
echo "Done"
}
main "$@"