diff --git a/dropshell-build/install_dropshell_build_host.sh b/dropshell-build/install_dropshell_build_host.sh new file mode 100755 index 0000000..a97c92a --- /dev/null +++ b/dropshell-build/install_dropshell_build_host.sh @@ -0,0 +1,304 @@ +#!/bin/bash + +set -euo pipefail + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + + +_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 +function is_package_installed() { + dpkg -l "$1" 2>/dev/null | grep -q "^ii" +} + +function install_packages() { + local PACKAGES + local HAVE_UPDATED=0 + + # 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"|"Debian GNU/Linux") + # Common packages for both Ubuntu and Debian + PACKAGES="nlohmann-json3-dev wget curl cmake ninja-build mold" + ;; + *) + 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_status "Installing $pkg..." + + # Update package lists + if [ "$HAVE_UPDATED" -eq 0 ]; then + print_status "Updating package lists..." + apt-get update + HAVE_UPDATED=1 + fi + + if ! sudo apt-get install -y "$pkg"; then + print_error "Failed to install $pkg" + exit 1 + fi + else + print_status "$pkg is already installed" + fi + done + +} + +function install_headers() { + # put libassert headers on the host. + if [ ! -f /usr/local/lib/libassert.a ]; then + 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 + sudo make install + cd ../.. + rm -rf libassert + fi +} + + +#---------------------------------------------------------------------------------------------------------- +# OpenSSL for musl cross toolchains +#---------------------------------------------------------------------------------------------------------- + +function install_openssl_musl() { + OPENSSL_VERSION=3.5.0 + + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + BUILD_DIR="${SCRIPT_DIR}/build" + MUSL_CROSS_DIR="$HOME/.musl-cross" + mkdir -p "$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" ] + } + + # Find all installed musl cross toolchains + TOOLCHAINS=() + for tc in "$MUSL_CROSS_DIR"/*-linux-musl-cross; do + [ -d "$tc" ] || continue + arch=$(basename "$tc" | sed 's/-linux-musl-cross//') + TOOLCHAINS+=("$arch") + done + + if [ ${#TOOLCHAINS[@]} -eq 0 ]; then + echo "No musl cross toolchains found in $MUSL_CROSS_DIR. Exiting." + exit 1 + fi + + echo "Found musl cross toolchains: ${TOOLCHAINS[*]}" + + for ARCH in "${TOOLCHAINS[@]}"; do + echo "===============================" + echo "Checking OpenSSL for $ARCH..." + echo "===============================" + if [ "$ARCH" = "x86_64" ]; then + MUSL_PREFIX="$MUSL_CROSS_DIR/x86_64-linux-musl-cross" + OPENSSL_TARGET=linux-x86_64 + elif [ "$ARCH" = "aarch64" ]; then + MUSL_PREFIX="$MUSL_CROSS_DIR/aarch64-linux-musl-cross" + OPENSSL_TARGET=linux-aarch64 + else + # Try to guess OpenSSL target for other musl toolchains + OPENSSL_TARGET="linux-$ARCH" + MUSL_PREFIX="$MUSL_CROSS_DIR/${ARCH}-linux-musl-cross" + fi + SYSROOT="$MUSL_PREFIX/${ARCH}-linux-musl/sysroot" + CC="$MUSL_PREFIX/bin/${ARCH}-linux-musl-gcc" + AR="$MUSL_PREFIX/bin/${ARCH}-linux-musl-ar" + RANLIB="$MUSL_PREFIX/bin/${ARCH}-linux-musl-ranlib" + + SKIP_BUILD=0 + if [ -f "$SYSROOT/usr/lib/libssl.a" ]; then + # Try to extract version from opensslv.h + OPENSSLV_H="$SYSROOT/usr/include/openssl/opensslv.h" + if [ -f "$OPENSSLV_H" ]; then + INSTALLED_VERSION=$(grep '# *define *OPENSSL_VERSION_TEXT' "$OPENSSLV_H" | sed -E 's/.*OpenSSL ([0-9.]+)[^ ]*.*/\1/') + if [ -n "$INSTALLED_VERSION" ]; then + echo "Found installed OpenSSL version: $INSTALLED_VERSION" + if version_ge "$INSTALLED_VERSION" "$OPENSSL_VERSION"; then + echo "OpenSSL $INSTALLED_VERSION is up-to-date (>= $OPENSSL_VERSION), skipping build for $ARCH." + SKIP_BUILD=1 + else + echo "OpenSSL $INSTALLED_VERSION is older than $OPENSSL_VERSION, will rebuild." + fi + else + echo "Could not determine installed OpenSSL version, will rebuild." + fi + else + echo "No opensslv.h found, will rebuild." + fi + fi + + if [ "$SKIP_BUILD" -eq 1 ]; then + echo + continue + fi + + cd "$BUILD_DIR" + if [ ! -d "openssl-${OPENSSL_VERSION}" ]; then + if [ ! -f "openssl-${OPENSSL_VERSION}.tar.gz" ]; then + wget "https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz" + fi + tar xf "openssl-${OPENSSL_VERSION}.tar.gz" + fi + cd "openssl-${OPENSSL_VERSION}" + + # Clean previous build for this arch + make clean || true + + 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"$(nproc)" + echo "Installing to $SYSROOT/usr ..." + make install_sw + cd "$BUILD_DIR" + echo "Done for $ARCH." + echo + # Remove build dir for next arch to avoid cross contamination + rm -rf "openssl-${OPENSSL_VERSION}" + tar xf "openssl-${OPENSSL_VERSION}.tar.gz" + done + + echo "OpenSSL built and installed for all detected musl toolchains." +} + + + +# ---------------------------------------------------------------------------------------------------------- +# 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://musl.cc" + if [ ! -d "$INSTALL_DIR/$TOOLCHAIN" ]; then + echo "Downloading $TOOLCHAIN musl cross toolchain..." + wget -nc -O "$TMPDIR/$TOOLCHAIN.tgz" "$MUSL_CC_URL/$TOOLCHAIN.tgz" + tar -C "$INSTALL_DIR" -xvf "$TMPDIR/$TOOLCHAIN.tgz" + fi +} + +function installmusl() { + echo "Installing musl toolchain" + + # Set install directory + if [ -n "${SUDO_USER:-}" ] && [ "$SUDO_USER" != "root" ]; then + USER_HOME=$(eval echo "~${SUDO_USER}") + else + USER_HOME="$HOME" + fi + INSTALL_DIR="$USER_HOME/.musl-cross" + mkdir -p "$INSTALL_DIR" + + TMPDIR=$(mktemp -d) + trap 'rm -rf "$TMPDIR"' EXIT + + TOOLCHAIN_LIST=( + "aarch64-linux-musl-cross" + "x86_64-linux-musl-cross" + ) + + for TOOLCHAIN in "${TOOLCHAIN_LIST[@]}"; do + install_musl_cross "$TOOLCHAIN" + check_path "$TOOLCHAIN" + done + + # Clean up + rm -rf "$TMPDIR" +} + + +#---------------------------------------------------------------------------------------------------------- +# Main +#---------------------------------------------------------------------------------------------------------- + +function main() { + + install_packages + + install_headers + + installmusl + + install_openssl_musl + +} + +main \ No newline at end of file